2015-04-12 98 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()沒有顯示任何工作。 –

相關問題