2017-03-03 47 views
4

我試圖按順序執行一系列的承諾,只有在先前解決後纔去下一個承諾。來自藍鳥文檔:藍鳥地圖系列

迭代器將不會被調用,直到它的前一個項目,並且該迭代器返回的該項目的承諾得到滿足。 http://bluebirdjs.com/docs/api/promise.mapseries.html

var Promise = require('bluebird'); 


function test(time) { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { 
      console.log(time); 
      resolve(time); 
     }, time); 
    }); 
} 

Promise.mapSeries([test(2000), test(1000), test(500), test(3000)], function(a) { 
    return a; 
}).then(function(results) { 
    console.log(results); 
}); 

我想到的是,測試函數內的console.log顯示:2000,1000,500,3000的順序。我期望,因爲正如文件所述,每個項目只有在先前解決之後才能進行。相反,我得到了500,1000,2000,3000,這反映了所有的功能都被稱爲instanstaneously。而且,結果確實按照它們被調用的順序顯示了結果,儘管這在目前是無關緊要的。

我誤解了一些東西嗎?

+0

_創建一個promise(這是'test'的作用)是一個同步操作。 – robertklep

+0

當然,我仍然期望藍鳥做一些魔術,並等待下一次測試,直到完成前一個測試。這不正是文件所說的嗎? – yBrodsky

+1

迭代器返回一個項目的承諾和本身承諾的項目(這是你的情況會發生什麼)之間有區別。一旦你調用'test',它返回的承諾「開始」(所以'setTimeout'被調用)。給出的答案顯示瞭如何推遲承諾的創建,直到Bluebird明確要求承諾(這是唯一可行的方式)。 – robertklep

回答

5

您的測試呼叫正在Promise.mapSeries有機會運行。另外mapSeries通常運行在承諾實例上。也許下面的例子有助於理解?注意如何這次測試(時間)返回一個函數。

function test(time) { 
    return function(value) { 
     return new Promise(function(resolve, reject) { 
      setTimeout(function() { 
       console.log('time', time); 
       resolve(time); 
      }, time); 
     }); 
    }; 
} 

Promise.resolve([test(2000), test(400), test(1000), test(1), test(5000)]) 
     .mapSeries(function(asyncMethodPassed) { 
    return asyncMethodPassed(); 
}).then(function(results) { 
    console.log('result', results); 
}); 
+0

很好,謝謝一堆。 – yBrodsky

+0

這只是我用自己的代碼一百次的一類問題:-) –