异步构造函数 [英] Asynchronous constructor
问题描述
我如何才能最好地处理以下情况?
我有一个需要一段时间才能完成的构造函数.
var Element = function Element(name){this.name = 名称;this.nucleus = {};this.load_nucleus(name);//这可能需要一秒钟.}var 氧 = 新元素(‘氧’);控制台日志(氧气.核);//返回 {},因为 load_nucleus 还没有完成.
我看到了三个选项,每个选项都显得与众不同.
一,给构造函数添加一个回调.
var Element = function Element(name, fn){this.name = 名称;this.nucleus = {};this.load_nucleus(名称,函数(){fn();//现在继续.});}Element.prototype.load_nucleus(name, fn){fs.readFile(name+'.json', function(err, data) {this.nucleus = JSON.parse(data);fn();});}var 氧气 = 新元素('氧气',函数(){控制台日志(氧气.核);});
二,使用 EventEmitter 来发出一个 'loaded' 事件.
var Element = function Element(name){this.name = 名称;this.nucleus = {};this.load_nucleus(name);//这可能需要一秒钟.}Element.prototype.load_nucleus(名称){var self = this;fs.readFile(name+'.json', function(err, data) {self.nucleus = JSON.parse(data);self.emit('加载');});}util.inherits(Element, events.EventEmitter);var 氧 = 新元素(‘氧’);氧气.一次('加载',功能(){控制台日志(this.nucleus);});
或者三个,阻塞构造函数.
var Element = function Element(name){this.name = 名称;this.nucleus = {};this.load_nucleus(name);//这可能需要一秒钟.}Element.prototype.load_nucleus(name, fn){this.nucleus = JSON.parse(fs.readFileSync(name+'.json'));}var 氧 = 新元素(‘氧’);控制台.日志(氧.核)
但我以前从未见过这样做过.
我还有哪些选择?
鉴于在 Node 中避免阻塞的必要性,事件或回调的使用并不奇怪(1).>
稍微编辑两个,你可以将它与一个合并:
var Element = function Element(name, fn){this.name = 名称;this.nucleus = {};if (fn) this.on('loaded', fn);this.load_nucleus(name);//这可能需要一秒钟.}...
虽然,就像示例中的 fs.readFile
一样,核心 Node API(至少)通常遵循静态函数的模式,在数据准备好时公开实例:
var Element = function Element(name,nucleus) {this.name = 名称;this.nucleus = 细胞核;};Element.create = 函数(名称,fn){fs.readFile(name+'.json', function(err, data) {无功核= 错误?null : JSON.parse(data);fn(错误,新元素(名称,核));});};Element.create('oxygen', function (err, elem) {如果(!错误){控制台日志(元素名称,元素.核);}});
<小时>
(1) 读取 JSON 文件应该不会花费很长时间.如果是的话,也许是为了数据而改变了存储系统.
How can I best handle a situation like the following?
I have a constructor that takes a while to complete.
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.
I see three options, each of which seem out of the ordinary.
One, add a callback to the constructor.
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);
});
Two, use EventEmitter to emit a 'loaded' event.
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);
});
Or three, block the constructor.
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)
But I haven't seen any of this done before.
What other options do I have?
Given the necessity to avoid blocking in Node, the use of events or callbacks isn't so strange(1).
With a slight edit of Two, you could merge it with 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.
}
...
Though, like the fs.readFile
in your example, the core Node APIs (at least) often follow the pattern of static functions that expose the instance when the data is ready:
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) It shouldn't take very long to read a JSON file. If it is, perhaps a change in storage system is in order for the data.
这篇关于异步构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!