我正试图使用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;
})
答案 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/