首先加入 bluebird 的 Promise 對象,然后寫一個輔助方法 makePromise 用來生成 Promise ,下面的 data 變量是演示用的數據,代表 setTimeout 的延時。
const Promise = require('bluebird');
function makePromise(name, delay) {
return new Promise((resolve) => {
console.log(`${name} started`);
setTimeout(() => {
console.log(`${name} completed`);
resolve(name);
}, delay);
});
}
const data = [2000, 1, 1000];
OK,首先看 Promise.all 方法,很簡單,他會等所有 Promise 執行完畢后,把結果放在數組里,注意這里 Promise 的執行不存在什么順序還是並發問題,因為 Promise 本身就代表一個已經執行的過程,所以 Promise.all 就是在等所有過程結束,代碼:
Promise.all(data.map((v, k) => makePromise(k, v))).then(res => {
console.log(res);
});
輸出:
0 started 1 started 2 started 1 completed 2 completed 0 completed [ 0, 1, 2 ] 0 started 1 started 2 started 1 completed 2 completed 0 completed [ 0, 1, 2 ]
然后是 Promise.map 方法,這個相當於把常見的 Array.map 創建 Promise 的過程和 Promise.all 結合起來,所以用 Promise.map 來實現上例的代碼是:
Promise.map(data, (v, k) => makePromise(k, v)).then(res => {
console.log(res)
});
輸出:
0 started 1 started 2 started 1 completed 2 completed 0 completed [ 0, 1, 2 ]
輸出和上面的 Promise.all 例子一樣。
另外, Promise.map 還可以加入一個 concurrency 參數,注意這個 concurrency 參數是控制同時並發創建的 Promise 個數,並且是不保證順序的,所以當 {concurrency: 1} 時,只會有一個 Promise 在運行,但是整個數組不保證是從左到右順序執行的。
Promise.reduce 方法才是一個順序執行 Promise 的方法,所謂順序執行,其實就是從左到右按順序去創建 Promise ,並且始終只有一個 Promise 在運行。看 bluebird 的 源碼 ,可以發現,一些順序執行的方法,比如 Promise.mapSeries 和 Promise.each ,都是基於 Promise.reduce 來實現的,這里的 reduce 和 Array.reduce 一樣,測試代碼:
Promise.reduce(data, (total, v, k) => { return makePromise(k, v).then(res => { return total + res; }); }, 0).then(res => { console.log(res); })
輸出:
0 started 0 completed 1 started 1 completed 2 started 2 completed 3
最后的 3 是所有 Promise 的結果總和,即 0+1+2 .
接下來是 Promise.mapSeries 方法,這個方法和 Promise.map 類似,只不過是順序執行的,代碼:
Promise.mapSeries(data, (v, k) => makePromise(k, v), 0).then(res => {
console.log(res);
})
輸出:
0 started 0 completed 1 started 1 completed 2 started 2 completed [ 0, 1, 2 ]
最后是 Promise.each 方法,和 Promise.mapSeries 方法類似,都是順序執行,區別是,返回的數組不是所有 Promise 的結果,而是傳入 Promise.each 方法的原始數據數組,如下代碼:
Promise.each(data, (item, index) => makePromise(index, item), 0).then(res => {
console.log(res);
});
輸出:
0 started 0 completed 1 started 1 completed 2 started 2 completed [ 0, 1, 2 ]
最后還是要看bluebird的文檔,里面還包含了其他好用的方式,比如delay等
