首页 > 解决方案 > 在javascript中取消异步调用链

问题描述

我正在研究在 javascript 中取消异步等待链的问题,我遇到了这条推文,作者在其中声明为了取消这样的链:

  call1();
  call2();
  call3();

您需要像这样包装它们:

 try {
    await Promise.race([
      call1(),
      isCanceled()
    ]);
  }
  catch (err) {
    if (err instanceof CancelationError) return;
  }

 try {
    await Promise.race([
      call2(),
      isCanceled()
    ]);
  }
  catch (err) {
    if (err instanceof CancelationError) return;
  }

 try {
    await Promise.race([
      call3(),
      isCanceled()
    ]);
  }
  catch (err) {
    if (err instanceof CancelationError) return;
  }

哪一种使,因为一旦你进入,await你就永远不会摆脱它,除非承诺解决或拒绝。

有人告诉我,您可以使用生成器取消整个链,而无需包装每个调用。

谁能解释如何在不包装每个异步调用的情况下包装整个链?

标签: javascriptecmascript-6

解决方案


是的,您可以将其包装在生成承诺的生成器中,然后为每个承诺进行取消竞赛:

async function run(cancel, fn) {
  const gen = fn();
  let result = gen.next();
  let next;
  while (!result.done) {
    try {
      next = await Promise.race([cancel, result.value]);
    } catch (err) {
      if (err instanceof CancelationError)
        result = gen.return();
      else
        result = gen.throw(err);
      continue;
    }
    result = gen.next(next);
  }
}

run(isCanceled(), function*() {
  yield call1();
  yield call2();
  yield call3();
});

推荐阅读