JavaScript
常见代码片段
Async Concurrent

异步任务并发量

原题:请实现如下函数,可以并发请求数据,所有的 URL 地址在 urls 参数中,同时可以通过 max 参数控制请求的并发度,当所有请求结束之后,需要执行 callback 回调函数。

这里通过 sleep 模拟实现

async function sleep(n, name = "test") {
  return new Promise((resolve) => {
    console.log("start", name, n);
    setTimeout(() => {
      console.log("end", name, n);
      resolve();
    }, n);
  });
}
 
// 限制并发数  items是异步函数队列
async function asyncPool({ max, items }) {
  const results = [];
  const pool = new Set();
 
  for (const item of items) {
    // 避免传入的不是 Promise
    const fn = async (item) => await item();
    const promise = fn(item);
 
    results.push(promise);
    pool.add(promise);
 
    // 无论执行结果是成功还是失败都清除
    const clean = () => pool.delete(promise);
    promise.then(clean, clean);
 
    if (pool.size >= max) {
      // 等待最快的 Promise 执行完毕,才会执行下一次 for 循环
      await Promise.race(pool);
    }
  }
  return Promise.allSettled(results);
}
 
async function start() {
  await asyncPool({
    max: 2,
    items: [
      () => sleep(1000, "1000"),
      () => sleep(4000, "4000"),
      () => sleep(3500, "3500"),
      () => sleep(5000, "5000"),
      () => sleep(2000, "2000"),
    ],
  });
  console.log("all done");
}
 
start();
// 执行结果
// start 1000 1000
// start 4000 4000
// end 1000 1000
// start 3500 3500
// end 4000 4000
// start 5000 5000
// end 3500 3500
// start 2000 2000
// end 2000 2000
// end 5000 5000
// all done