devStandard/docs/learning/3-js/4-promise-all限制并发.md
2025-03-29 14:35:49 +08:00

54 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` 的结果