Promise 与 q 框架和 Node.js 中的回调模式?
Posted
技术标签:
【中文标题】Promise 与 q 框架和 Node.js 中的回调模式?【英文标题】:Promise with q framework and the callback pattern in Node.js? 【发布时间】:2013-02-05 09:10:21 【问题描述】:如果您使用 Node.js 进行编程几天,即使 q framework 有据可查,也很难理解。但我喜欢了解它!
var Q = require('q');
var fs = require('fs');
// Make the promise manually (returns a value or throws an error)
var read1 = fs.readFile(fname, enc, function (err, data)
if(err) throw err;
return data;
);
// Convenient helper for node, equivalent to read1?
var read2 = Q.nfbind(fs.readFile);
// Uh?!
var read3 = function (fname, enc)
var deferred = Q.defer();
fs.readFile(fname, enc, function (error, text)
if (error)
deferred.reject(new Error(error));
else
deferred.resolve(text);
return deferred.promise;
);
;
// Execute
Q.fncall(read1).then(function (data) , function (err) ).done();
read1
、read2
和 read3
是否等效?每次函数的最后一个参数接受function (err, value)
风格的回调时,我可以使用Q.nfbind
吗?
【问题讨论】:
【参考方案1】:您的示例中有一些错误。
读取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
。
在我的 cmets 中,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链中捕获它们,这通常是不可取的。见the deferred antipattern。
【讨论】:
可爱的答案。不要忘记.done()
的奖励积分! :)以上是关于Promise 与 q 框架和 Node.js 中的回调模式?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在使用promise时使用Q,bluebird框架? [复制]
使用 Q Promise 的 node.js 项目的代码覆盖率