一尘不染

异步构造函数

node.js

我如何最好地处理以下情况?

我有一个构造函数,需要一些时间才能完成。

var Element = function Element(name){
   this.name = name;
   this.nucleus = {};

   this.load_nucleus(name); // This might take a second.
}

var oxygen = new Element('oxygen');
console.log(oxygen.nucleus); // Returns {}, because load_nucleus hasn't finished.

我看到了三个选项,每个选项似乎都与众不同。

一种 ,向构造函数添加回调。

var Element = function Element(name, fn){
   this.name = name;
   this.nucleus = {};

   this.load_nucleus(name, function(){
      fn(); // Now continue.
   });
}

Element.prototype.load_nucleus(name, fn){
   fs.readFile(name+'.json', function(err, data) {
      this.nucleus = JSON.parse(data); 
      fn();
   });
}

var oxygen = new Element('oxygen', function(){  
   console.log(oxygen.nucleus);
});

第二 ,使用EventEmitter发出“已加载”事件。

var Element = function Element(name){
   this.name = name;
   this.nucleus = {};

   this.load_nucleus(name); // This might take a second.
}

Element.prototype.load_nucleus(name){
   var self = this;
   fs.readFile(name+'.json', function(err, data) {
      self.nucleus = JSON.parse(data); 
      self.emit('loaded');
   });
}

util.inherits(Element, events.EventEmitter);

var oxygen = new Element('oxygen');
oxygen.once('loaded', function(){
   console.log(this.nucleus);
});

或三 ,阻止构造函数。

var Element = function Element(name){
   this.name = name;
   this.nucleus = {};

   this.load_nucleus(name); // This might take a second.
}

Element.prototype.load_nucleus(name, fn){
   this.nucleus = JSON.parse(fs.readFileSync(name+'.json'));
}

var oxygen = new Element('oxygen');
console.log(oxygen.nucleus)

但我以前从未见过任何完成的事情。

我还有什么其他选择?


阅读 287

收藏
2020-07-07

共1个答案

一尘不染

鉴于有必要避免在Node中进行阻塞,事件或回调的使用并不奇怪(1)。

稍加修改为2,即可将其与One合并:

var Element = function Element(name, fn){
    this.name = name;
    this.nucleus = {};

    if (fn) this.on('loaded', fn);

    this.load_nucleus(name); // This might take a second.
}

...

不过,就像fs.readFile您的示例中一样,核心Node API(至少)通常遵循静态函数的模式,这些静态函数会在数据准备就绪时公开实例:

var Element = function Element(name, nucleus) {
    this.name = name;
    this.nucleus = nucleus;
};

Element.create = function (name, fn) {
    fs.readFile(name+'.json', function(err, data) {
        var nucleus = err ? null : JSON.parse(data);
        fn(err, new Element(name, nucleus));
    });
};

Element.create('oxygen', function (err, elem) {
    if (!err) {
        console.log(elem.name, elem.nucleus);
    }
});

(1)读取JSON文件应该不需要很长时间。如果是这样,则可能是为了更改数据而更改了存储系统。

2020-07-07