Javascript : async constructor pattern

标签 javascript node.js async.js

我正在定义一个类,它实例化几个依赖于先前模块的模块。模块本身可能需要异步操作才能准备好(即建立 mysql 连接),因此我为每个构造函数提供了一个回调,一旦模块准备好就会调用。但是我在实例化立即准备好的类时遇到了问题:

var async = require('async');

var child = function(parent, cb) {
    var self = this;
    this.ready = false;

    this.isReady = function() {
        return self.ready;
    }

    /* This does not work, throws error below stating c1.isReady is undefined*/
    cb(null, true);

    /* This works */
    setTimeout(function() {      
        self.ready = true;
        cb(null, true);
    }, 0);
}


var Parent = function(cb) {
    var self = this;
    async.series([
        function(callback){
            self.c1 = new child(self, callback);                       
        },
        function(callback){
            self.c2 = new child(self, callback);   
        }
    ],
    function(err, results){
        console.log(self.c1.isReady(), self.c2.isReady);
        console.log(err, results);
    });
}

var P = new Parent();

我猜问题是在构造函数中调用 cb 意味着异步会在构造函数完成之前继续执行下一个函数。有更好的方法吗?我考虑过使用 promise ,但我发现这种方法更容易理解/遵循。

最佳答案

当一切都同步时,您将不得不延迟对回调的调用,因为回调中的任何代码都还不能引用该对象(如您所见)。因为构造函数还没有执行完,所以对它的返回值的赋值也还没有完成。

您可以将对象传递给回调并强制回调使用该引用(它将存在并完全形成),但是您需要人们知道他们不能使用通常接受的做法,所以这很重要最好确保只异步调用回调,然后人们可以按照他们期望的正常方式编写代码。

在 node.js 中,使用 process.nextTick() 代替 setTimeout() 会更有效地实现您的目标。参见 this article了解更多详情。

var child = function(parent, cb) {
    var self = this;
    this.ready = false;

    this.isReady = function() {
        return self.ready;
    }

    /* This works */
    process.nextTick(function() {      
        self.ready = true;
        cb(null, true);
    }, 0);
}

这是一般性的观察。出于与此相关的原因,许多人(包括我自己)认为将任何异步操作放在构造函数中会使事情过于复杂。相反,大多数需要执行异步操作以进行 self 设置的对象将提供 .init().connect() 方法或类似方法。然后,您像往常一样以同步方式构造对象,然后单独启动初始化的异步部分并将回调传递给它。这让你完全远离这个问题。

如果/当你想使用 promises 来跟踪你的异步操作(这是一个很好的功能方向),让构造函数返回对象和 .init() 返回 promise 的操作。尝试从构造函数返回对象和 promise 会变得很困惑,使用它进行编码甚至更困惑。

然后,使用 promises 你可以这样做:

var o = new child(p);
o.init().then(function() {
    // object o is fully initialized now
    // put code in here to use the object
}, function(err) {
    // error initializing object o
});

关于Javascript : async constructor pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28227480/

相关文章:

angularjs - Angular-fullstack 获取用户 ID

javascript - 非常简单的 Node.js 客户端在多次 http 请求后抛出错误 ENOBUFS

node.js - 尽管出现错误,async.series() 仍继续执行下一个函数

Javascript:将 Math.sqrt 转换为 int?

javascript - iframe跨域访问

javascript - 当我使用 jQuery.ajax 获取脚本时抛出语法错误

node.js - 如何将配置的 Passport 对象传递到 Express4 中的路由模块?

node.js - 在 Node js 的 async.forEach 中返回值?

javascript - 使用 Hapi 和异步的 API - 如何清空数组/在 "reply"之后或在每个新的 "get"处立即执行某些操作?

javascript - 避免重复的代码并提取此功能