关于 Promise.all, map, reduce, mapSeries, each 方法

首先加入 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等


posted @ 2017-01-19 14:35  都市烟火  阅读(3041)  评论(0编辑  收藏  举报