异步并发调用

本文最后更新于:2020年12月13日 晚上

问题

你觉得下面这段代码会怎么打印?这里使用异步模拟了 10 个 thread,然后从 generator 里面迭代取值

const sleep = (sec) =>
  new Promise((res, rej) => {
    setTimeout(res, sec * 1000);
  });
const group = (arr, kFn) =>
  arr.reduce((res, item) => {
    const i = kFn(item);
    res[i] = (res[i] || 0) + 1;
    return res;
  }, {});

const fibGenerator = function* (n) {
  let [a, b] = [0, 1];
  for (let i = 0; i < n; i++) {
    yield a;
    [a, b] = [b, a + b];
  }
};
const fibIterator = fibGenerator(100);
// 开十个 thread
const idxArr = Array(10)
  .fill(0)
  .map((_, i) => i);
const arr = [];
Promise.all(
  idxArr.map(async (i) => {
    for (const num of fibIterator) {
      arr.push([i, num]);
      // 如果改成 await sleep(0) 呢?
      await sleep(Math.random());
    }
  })
).then(() => {
  console.log(
    arr.length,
    arr,
    group(arr, ([i]) => i)
  );
});

答案

主要考察并发异步和迭代器的知识

修改前

  • 100 个,因为 generator 只能迭代 100 次
  • 没什么规律的数组,因为队列在第一次之后追加的 idx 顺序是不确定的,会是 1,2,3…9 然后后面线程就不能确定了
  • 每个线程运行次数至少为 1

修改后

  • 同上
  • 确定的数组,线程是 0,1,2…9 的循环,对应的值则是从 0-99 对应的斐波那契数列递增
  • 确定的对象,每个线程运行次数均为 10

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!