2015-04-12 67 views
13

在一个承诺库蓝鸟有函数promisifyAll或其他类似的库,声称将回调模式的异步函数转换为基于承诺,即。 resolve(),reject()done() ..那么它是如何工作的?promisifyAll如何工作,或者它的工作要求是什么?

例如:

function myAsync1 (data, url, callBack) {...} 

,如果我把它放在

Promise.promisify(myAsycn1); 

然后将我喜欢这个功能工作..

myAsync1('{..}', 'http://..').then(function(){...}); 

这也一直困扰着我。是否有一种模式,异步非诺言库或功能需要遵循蓝鸟promisifyAll将它们转换为基于承诺的方法或有一些魔法,将它们转换。

如果没有,那么有什么要求,它是如何与像的MongoDB等

+0

请注意,您的功能不是“转换”,功能是不可变的。相反,'Promise.promisify'不会返回一个* new *函数,它会用回调调用旧函数。 – Bergi

+1

[尝试了解promisification如何与BlueBird合作](http://stackoverflow.com/q/26391419/1048572) – Bergi

+0

@Bergi它可能是重复的,但它的标题在SEO方面措辞如此糟糕以至于在搜索之后四个小时,我没有遇到过一次,事实上,它更接近点击诱饵。 –

回答

20

有没有一种模式的异步非承诺库或者功能需要遵循蓝鸟promisifyAll将它们转换为基于承诺的方法

是的,有规律可循的。它转换的函数必须将回调作为它们的最后一个参数。此外,它必须传递一个错误作为回调的第一个参数(如果没有错误,则为null),返回值作为第二个参数。

蓝鸟promisify功能是非常困难的,因为优化的跟随,所以我将展示一个简单的方法就可以写成:

function promisify(fn) { 
    return function() { 
    var that = this; // save context 
    var args = slice.call(arguments); // turn into real array 
    return new Promise(function(resolve, reject) { 
     var callback = function(err, ret) { // here we assume the arguments to 
              // the callback follow node.js 
              // conventions 
     if(err != undefined) { 
      reject(err); 
     } else { 
      resolve(ret); 
     } 
     }; 
     fn.apply(that, args.concat([callback])); // Now assume that the last argument will 
               // be used as a callback 
    }); 
    }; 
} 

现在我们可以通过在目标上循环功能实现promisifyAll对象和每个使用promisify

+0

所以如果这个约定那么它意味着asyncjs不遵循约定? https://gist.github.com/techsin/18a6b6d36ed0205a443a 在这里你可以看到,如果只有回调函数是第一个参数,函数才能工作。这种行为对于asyncjs是独一无二的吗? –

+0

对于承诺......规则是该函数应该接收回调作为最后一个参数,并且必须以err作为第一个参数调用该回调,对吧? ..但是,在他们身边,我看到像'Promise.promisify('request'); Promise.promisify( 'FS'); Promise.promisify('mongoose');'等这些所有模块/库,巧合,遵循这些要求。 –

+1

@MuhammadUmer这是一个使用'async'库的非常具有误导性的例子。传递给'async.series'的函数只需要一个参数,即回调函数。这些函数将不会得到'err'参数。 –

2

promisifyAll()方法promisifies正在被称为一个参数整个模块或对象现有的库工作。这意味着对象的每个属性的副本都是使用Async后缀创建的,这实际上是相同方法的promisified版本,即可以对其使用.then().done()方法。

例如,如果你在someModule模块doSomething()方法,调用Promise.promisifyAll(someModule)新方法称为doSomethingAsync()模块中创建后。您可以这样使用:

var someModule = require('some-module'); 
Promise.promisifyAll(someModule); 
someModule.doSomethingAsync().then(function(result) { 
    // do whatever you want with result, this function runs after doSomthingAsync() 
    // is finished and the returned value is stored in 'result' variable. 
}); 

查看bluebird API documentation了解更多信息。

+0

我知道结局的结果是什么,但我想知道的是如何?承诺依靠内部调用,并以某种方式传递错误,所以你可以做'.catch' ...所以doSOmething()没有显示任何工作。 –

相关问题