【问题标题】:Proper way to Abort (stop) running async/await function?中止(停止)运行异步/等待功能的正确方法?
【发布时间】:2021-11-26 00:48:29
【问题描述】:

在 SE 上还有其他主题,但大多数都是 5 年前的。在 JS 中取消等待调用的当前最新方法是什么?即

async myFunc(){
    let response = await oneHourLastingFunction();
    myProcessData(response);
}

在特定时刻应用程序决定不再等待oneHourLastingFunction,但它卡在“等待”中。怎么取消呢?任何标准的取消令牌/abortControllers 的承诺方式?

【问题讨论】:

  • 目前在 JS 中取消 await 调用的最新方法是什么?”除了不可能?那里没有任何新的发展。除非您专门使自己的功能可取消,否则就是这样。
  • 回答说“您发现的旧问题仍然是最新的”?对我来说听起来像是重复的。
  • @VLAZ 那么 AbortControllers 呢? javascript.plainenglish.io/…
  • @vlaz 如果过去 6 年没有更新,那真可惜。您可以将主题标记为重复。
  • 你可以使用Promise.race([oneHourLastingFunction(), delay(time)]),但是它不会取消其他操作......所以你应该使用AbortControllers,大多数API都支持这个......

标签: javascript asynchronous promise cancellation


【解决方案1】:

取消异步过程仍然不是一件容易的事,尤其是当您需要深度取消和流程控制时。目前没有原生解决方案。您可以在本地做的所有事情:

  • 将 AbortController 实例传递给要取消的每个嵌套异步函数
  • 为所有内部微任务(请求、计时器等)订阅信号
  • 可选择从信号中取消订阅已完成的微任务
  • 调用控制器的abort方法取消所有订阅的微任务

这是一个非常冗长且棘手的解决方案,可能存在内存泄漏。

我可以建议我自己的解决方案来应对这个挑战 - c-promise2,它提供了可取消的承诺和 ECMA 异步函数的可取消替代方案 - 生成器。

这是一个基本示例 (Live Demo):

import { CPromise } from "c-promise2";

// deeply cancelable generator-based asynchronous function
const oneHourLastingFunction = CPromise.promisify(function* () {
  // optionally just for logging
  this.onCancel(() =>
    console.log("oneHourLastingFunction::Cancel signal received")
  );
  yield CPromise.delay(5000); // this task will be cancelled on external timeout
  return "myData";
});

async function nativeAsyncFn() {
  await CPromise.delay(5000);
}

async function myFunc() {
  let response;
  try {
    response = await oneHourLastingFunction().timeout(2000);
  } catch (err) {
    if (!CPromise.isCanceledError(err)) throw err;
    console.warn("oneHourLastingFunction::timeout", err.code); // 'E_REASON_TIMEOUT'
  }
  await nativeAsyncFn(response);
}

const nativePromise = myFunc();

深度可取消解决方案(所有功能均可取消)(Live Demo):

import { CPromise } from "c-promise2";

// deeply cancelable generator-based asynchronous function
const oneHourLastingFunction = CPromise.promisify(function* () {
  yield CPromise.delay(5000);
  return "myData";
});

const otherAsyncFn = CPromise.promisify(function* () {
  yield CPromise.delay(5000);
});

const myFunc = CPromise.promisify(function* () {
  let response;
  try {
    response = yield oneHourLastingFunction().timeout(2000);
  } catch (err) {
    if (err.code !== "E_REASON_TIMEOUT") throw err;
    console.log("oneHourLastingFunction::timeout");
  }
  yield otherAsyncFn(response);
});

const cancellablePromise = myFunc().then(
  (result) => console.log(`Done: ${result}`),
  (err) => console.warn(`Failed: ${err}`)
);

setTimeout(() => {
  console.log("send external cancel signal");
  cancellablePromise.cancel();
}, 4000);

【讨论】:

    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 2013-02-26
    • 2020-08-01
    • 1970-01-01
    相关资源
    最近更新 更多