假設這個簡單的代碼:如何延遲所有對JavaScript對象的任何方法的調用,直到對象被初始化?
/*jslint node: true */
"use strict";
function MyClass(db) {
var self = this;
this._initError = new Error("MyClass not initialized");
db.loadDataAsyncronously(function(err, data) {
if (err) {
self._initError =err;
} else {
self._initError = null;
self.data = data;
}
});
}
MyClass.prototype.getA = function(cb) {
if (this._initError) {
return cb(this._initError);
}
return cb(null, this.data.a);
};
MyClass.prototype.getB = function(cb) {
if (this._initError) {
return cb(this._initError);
}
return cb(null, this.data.b);
};
var db = {
loadDataAsyncronously: function(cb) {
// Emulate the load process from disk.
// Data will be available later
setTimeout(function() {
cb(null, {
a:"Hello",
b:"World"
});
},1000);
}
};
var obj = new MyClass(db);
obj.getA(function (err, a) {
if (err) {
console.log(err);
} else {
console.log("a: " + a);
}
});
obj.getB(function (err, b) {
if (err) {
console.log(err);
} else {
console.log("a: " + b);
}
});
,因爲當被稱爲木屐和getB方法obj不初始化這給出了一個錯誤。我希望在對象初始化之前調用的任何方法都會自動延遲,直到類完成其初始化。
一個解決這個問題的方法是這樣:
/*jslint node: true */
"use strict";
function MyClass(db) {
var self = this;
self._pendingAfterInitCalls = [];
db.loadDataAsyncronously(function(err, data) {
if (!err) {
self.data = data;
}
self._finishInitialization(err);
});
}
MyClass.prototype.getA = function(cb) {
this._waitUntiliInitialized(function(err) {
if (err) {
return cb(err);
}
return cb(null, this.data.a);
});
};
MyClass.prototype.getB = function(cb) {
this._waitUntiliInitialized(function(err) {
if (err) {
return cb(err);
}
return cb(null, this.data.b);
});
};
MyClass.prototype._finishInitialization = function(err) {
this._initialized=true;
if (err) {
this._initError = err;
}
this._pendingAfterInitCalls.forEach(function(call) {
call(err);
});
delete this._pendingAfterInitCalls;
};
MyClass.prototype._waitUntiliInitialized = function(cb) {
var bindedCall = cb.bind(this);
if (this._initialized) {
return bindedCall(this._initError);
}
this._pendingAfterInitCalls.push(bindedCall);
};
var db = {
loadDataAsyncronously: function(cb) {
// Emulate the load process from disk.
// Data will be available later
setTimeout(function() {
cb(null, {
a:"Hello",
b:"World"
});
},1000);
}
};
var obj = new MyClass(db);
obj.getA(function (err, a) {
if (err) {
console.log(err);
} else {
console.log("a: " + a);
}
});
obj.getB(function (err, b) {
if (err) {
console.log(err);
} else {
console.log("a: " + b);
}
});
但在我看來,大量的開銷,以每類下面的這個模式被寫入。
有沒有更好的方法來處理這個功能?
是否存在任何庫來簡化此功能?
我相當懷疑你正在用異步回調中的所有return語句完成任何事情。那些返回值只是回到異步基礎架構,而不是回到原來的調用者。 – jfriend00
同意,我只是刪除了回報。 – jbaylina