Luk*_*rns 51 javascript constructor asynchronous 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.
Run Code Online (Sandbox Code Playgroud)
我看到三种选择,每种选择都与众不同.
一,向构造函数添加回调.
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);
});
Run Code Online (Sandbox Code Playgroud)
二,使用EventEmitter发出'loaded'事件.
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);
});
Run Code Online (Sandbox Code Playgroud)
或者三,阻止构造函数.
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)
Run Code Online (Sandbox Code Playgroud)
但我以前没有见过这种做法.
我还有其他选择吗?
tim*_*tim 25
更新2:这是使用异步工厂方法的更新示例.注意,如果在浏览器中运行,则需要节点8或Babel.
class Element {
constructor(nucleus){
this.nucleus = nucleus;
}
static async createElement(){
const nucleus = await this.loadNucleus();
return new Element(nucleus);
}
static async loadNucleus(){
// do something async here and return it
return 10;
}
}
async function main(){
const element = await Element.createElement();
// use your element
}
main();
Run Code Online (Sandbox Code Playgroud)
更新:下面的代码被投票了几次.但是我发现这种方法使用静态方法要好得多:https: //stackoverflow.com/a/24686979/2124586
使用promises的ES6版本
class Element{
constructor(){
this.some_property = 5;
this.nucleus;
return new Promise((resolve) => {
this.load_nucleus().then((nucleus) => {
this.nucleus = nucleus;
resolve(this);
});
});
}
load_nucleus(){
return new Promise((resolve) => {
setTimeout(() => resolve(10), 1000)
});
}
}
//Usage
new Element().then(function(instance){
// do stuff with your instance
});
Run Code Online (Sandbox Code Playgroud)
Jon*_*ski 11
鉴于必须避免在Node中阻塞,事件或回调的使用并不那么奇怪(1).
稍微编辑两个,您可以将它与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.
}
...
Run Code Online (Sandbox Code Playgroud)
虽然,与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);
}
});
Run Code Online (Sandbox Code Playgroud)
(1)读取JSON文件不应该花很长时间.如果是,也许存储系统的变化是为了数据.
| 归档时间: |
|
| 查看次数: |
21348 次 |
| 最近记录: |