您的示例中有一些错误。
读1
这不是“手动做出承诺”,这只是进行正常的异步调用。在您的代码中,您readFile
立即调用,read1
其返回值readFile
也是undefined
. 要获得类似于的行为read2
,read3
您需要执行以下操作:
var read1 = function(fname, env, success, error){
fs.readFile(fname, enc, function (err, data) {
// Throwing here would just crash your application.
if(err) error(err);
// Returning from inside 'readFile' does nothing, instead you use a callback.
else success(data);
});
};
读取2
// Not equivalent to read1 because of the notes above,
// Equivalent to read3, with the fixes I mention below.
var read2 = Q.nfbind(fs.readFile);
读3
var read3 = function (fname, enc) {
var deferred = Q.defer();
fs.readFile(fname, enc, function (error, text) {
if (error) {
// 'error' is already an error object, you don't need 'new Error()'.
deferred.reject(error);
} else {
deferred.resolve(text);
}
// HERE: Again returning a value from 'readFile' does not make sense.
return deferred.promise;
});
// INSTEAD: Return here, so you can access the promise when you call 'read3'.
return deferred.promise.
};
您确实可以nfbind
在将回调作为最后一个参数的任何东西上使用。根据我的评论,read2
实现read3
相同的目标,即创建一个函数,该函数将采用文件名和编码,并返回一个 promise 对象。
对于那些,你可以这样做:
read2('file.txt', 'utf8').then(function (data) {}, function (err) {}).done();
read3('file.txt', 'utf8').then(function (data) {}, function (err) {}).done();
对于read1
,您可以这样称呼它:
read1('file.txt', 'utf8', function (data) {}, function (err) {});
更新
自从回答这个问题以来,标准承诺已经发生了一些变化,如果您倾向于read3
,我建议您执行以下操作:
var read4 = function (fname, enc) {
return Q.promise(function(resolve, reject){
fs.readFile(fname, enc, function (error, text) {
if (error) {
// 'error' is already an error object, you don't need 'new Error()'.
reject(error);
} else {
resolve(text);
}
});
});
};
这更符合标准 ES6 承诺和 bluebird,因此您可以更轻松地推进代码。使用中提到的方法read3
还引入了同步抛出异常而不是在 Promise 链中捕获它们的可能性,这通常是不可取的。请参阅延迟反模式。