试图了解promisification如何与BlueBird一起使用

时间:2014-10-15 20:21:25

标签: node.js bluebird

我正试图使用​​Bluebird library for Node.js包围承诺。

下面是一个简单的例子,它不能像我期望的那样工作。

var Promise = require("bluebird");

var myObj = {
  add: function(op1, op2) {
    return op1 + op2;
  }
};

// Sync call to add method -> 7
console.log(myObj.add(3,4));

var myObjAsync = Promise.promisifyAll(myObj);

// Async call to promisified add method -> nothing written to console
myObjAsync.addAsync(2,3).then(function(data) {
  console.log(data);
  return data;
})

我或者错过了承诺或蓝鸟的一些(主要)概念。

提前感谢您的帮助。

编辑:根据jfriend00的反馈修订(现在正在运行的版本)。

var Promise = require("bluebird");

var myObj = {
  add: function(op1, op2) {
    return op1 + op2;
  }
  , add2: function(op1, op2, callback) {
    callback(null, op1 + op2);
  }

};

// Sync call to add method -> 7
console.log(myObj.add(3,4));

var myObjAsync = Promise.promisifyAll(myObj);

// Async call to promisified add method -> nothing written to console
myObjAsync.addAsync(2,3).then(function(data) {
  console.log("%j", data);
  return data;
})

// Async call to promisified add2 method -> 5
myObjAsync.add2Async(2,3).then(function(data) {
  console.log("%j", data);
  return data;
})

1 个答案:

答案 0 :(得分:12)

要使promisifyAll()起作用,该函数必须是异步的,并且传递给函数的最后一个参数必须是完成回调,并且完成回调必须作为其第一个参数,一个错误参数是假的当没有错误并且返回值作为第二个参数时(如果有值)。

您的功能不符合任何这些标准。


以下摘自Bluebird doc for .promisifyAll()

  

假设目标方法符合node.js回调   接受回调作为最后一个参数并调用它的约定   回调,错误作为第一个参数和成功值   第二个论点。如果node方法使用multiple调用其回调   成功价值,履行价值将是他们的一系列。

请记住.promisifyAll()无法对异步操作进行同步操作。做什么是采取符合特定调用约定的异步操作,并通过挂钩回调并测试回调的参数来检测成功或失败并传播返回值,从而将其包装到promise中。


如果您对Bluebird如何做到这一点感到好奇,您可以检查他们的实际代码here on Github,但如果没有一些重要的研究,那么完全按照它做的事情并不容易。

这是一个简单版本的promisify函数,只是看看它做了什么(我建议使用Bluebird来获取所有其他功能而不是这个)。

// --------------------------------------------------------------
// promisify(fn, obj)
//
// Pass an async function that takes as its last argument a callback
// that conforms to the node.js callback calling convention function(err, result)
// passing obj is optional.  If present the function passed in will be called
// as obj.method()
//
// Returns: New function that when called will return a promise.
// --------------------------------------------------------------

function promisify(fn, obj) {
    if (typeof fn !== "function") {
        throw new Error("fn argument to promisify() must be function");
    }
    // obj is optional and may be undefined
    // if present, it will be used as context to call fn as in obj.fn()
    return function(/* args */) {
        // make copy of arguments object into a real array in a way that
        // does not prevent interpreter optimizations
        var args = new Array(arguments.length);
        for (var i = 0; i < args.length; i++) {
            args[i] = arguments[i];
        }
        return new Promise(function(resolve, reject) {
            // add our callback function at the end of the args list
            var resultMany;
            args.push(function(err, result) {
                if (err) {
                    reject(err);
                } else {
                    // if 0 or 1 result, then just return it as a simple value
                    if (arguments.length <= 2) {
                        resolve(result);
                    } else {
                        // if more than one result came with the callback function, 
                        // then put it into an array so we can resolve with a single value (the array of results)
                        // skip the first argument which is the err value
                        resultMany = new Array(arguments.length - 1);
                        for (var i = 0; i < arguments.length - 1; i++) {
                            resultMany[i] = arguments[i + 1];
                        }
                        resolve(resultMany);
                    }
                }
            });
            // call original function with our callback as last argument
            fn.apply(obj, args);
        });
    }
}

以下是此promisify()函数的工作演示:https://jsfiddle.net/jfriend00/m1265vos/