Promise with q framework和Node.js中的回调模式?

Promise with q framework和Node.js中的回调模式?,node.js,asynchronous,promise,q,Node.js,Asynchronous,Promise,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

如果您使用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();

read1
read2
read3
是否等效?每次函数的最后一个参数接受
函数(err,value)
样式的回调时,我是否可以使用
Q.nfbind

您的示例中有一些错误

阅读1 这不是“手动做出承诺”,这只是进行一个普通的异步调用。在代码中,您可以立即调用
readFile
,因此
read1
将是
readFile
的返回值,它是
未定义的
。要获得类似于
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);
  });
};
read1('file.txt', 'utf8', function (data) {}, function (err) {});
阅读2 阅读3 您确实可以对任何将回调作为最后一个参数的对象使用
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
,您可以这样称呼它:

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);
  });
};
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
中提到的方法还引入了同步抛出异常的可能性,而不是在承诺链中捕获异常,这通常是不可取的。请参阅。

回答得很好。不忘记
.done()
!:)的奖励积分