用Q框架和Node.js中的callback模式承诺?

即使有良好的文档化的Q框架 ,如果您使用Node.js编程几天,也是很难理解的。 但我喜欢了解它!

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(); 

read1read2read3相同? 每当函数的最后一个参数接受function (err, value)样式function (err, value)的callback函数时,我可以使用Q.nfbind吗?

你的例子中有一些错误。

READ1

这不是“手动作出承诺”,这只是做一个正常的asynchronous调用。 在你的代码中,你立即调用readFile ,所以read1将是readFile的返回值,它是undefined 。 要获得类似于read2read3的行为,您需要执行以下操作:

 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); }); }; 

READ2

 // 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. }; 

你确实可以在任何需要callback的东西上使用nfbind作为最后一个参数。 通过我的评论, read2read3完成了相同的目标,即创build一个函数,它将采用文件名和编码,并返回一个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 ,我build议做以下几点:

 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承诺,并与蓝鸟,所以你将有一个更容易的代码向前移动的时间。 使用read3提到的方法也引入了同步抛出exception的可能性,而不是将它们捕获在承诺链中,这通常是不希望的。 请参阅延迟的反模式 。