54 lines
2.5 KiB
Markdown
54 lines
2.5 KiB
Markdown
# promise all 并发限制
|
||
|
||
[async-pool](https://link.segmentfault.com/?url=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Ftiny-async-pool)、[es6-promise-pool](https://link.segmentfault.com/?url=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fes6-promise-pool)、[p-limit](https://link.segmentfault.com/?url=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fp-limit)
|
||
|
||
async-pool的代码:
|
||
|
||
```js
|
||
function asyncPool(poolLimit, array, iteratorFn) {
|
||
let i = 0;
|
||
const ret = [];
|
||
const executing = [];
|
||
const enqueue = function () {
|
||
// 边界处理,array为空数组
|
||
if (i === array.length) {
|
||
return Promise.resolve();
|
||
}
|
||
// 每调一次enqueue,初始化一个promise
|
||
const item = array[i++];
|
||
const p = Promise.resolve().then(() => iteratorFn(item, array));
|
||
// 放入promises数组
|
||
ret.push(p);
|
||
// promise执行完毕,从executing数组中删除
|
||
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
|
||
// 插入executing数字,表示正在执行的promise
|
||
executing.push(e);
|
||
// 使用Promise.rece,每当executing数组中promise数量低于poolLimit,就实例化新的promise并执行
|
||
let r = Promise.resolve();
|
||
if (executing.length >= poolLimit) {
|
||
r = Promise.race(executing);
|
||
}
|
||
// 递归,直到遍历完array
|
||
return r.then(() => enqueue());
|
||
};
|
||
return enqueue().then(() => Promise.all(ret));
|
||
}
|
||
```
|
||
|
||
因为是promise加上递归,所以在代码注释上不太好标注执行顺序,但是大概的逻辑可以总结为:
|
||
|
||
1. 从`array`第1个元素开始,初始化`promise`对象,同时用一个`executing`数组保存正在执行的promise
|
||
2. 不断初始化promise,直到达到`poolLimt`
|
||
3. 使用`Promise.race`,获得`executing`中promise的执行情况,当有一个promise执行完毕,继续初始化promise并放入`executing`中
|
||
4. 所有promise都执行完了,调用`Promise.all`返回
|
||
|
||
使用方式就是:
|
||
|
||
```js
|
||
const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
|
||
return asyncPool(2, [1000, 5000, 3000, 2000], timeout).then(results => {
|
||
...
|
||
});
|
||
```
|
||
|
||
> * `Promise.all(iterable)` 方法返回一个 `Promise` 实例,此实例在 `iterable` 参数内所有的 `promise` 都"完成(resolved)"或参数中不包含 `promise` 时回调完成(resolve);如果参数中 `promise` 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 `promise` 的结果 |