NodeJS:如何终止正在执行异步任务的类实例?
解决方案
推荐使用标准JS内置的AbortController实现异步任务的统一取消,无需轮询,可维护性更高,实现逻辑如下:
第一步:改造Example类支持取消信号
class Example { // 调用start时传入abortSignal信号 start(signal) { return new Promise(async (resolve, reject) => { // 提前处理已触发取消的场景 if (signal.aborted) { return reject(new Error('KILLED')) } // 监听取消事件,触发时直接终止Promise const onAbort = () => reject(new Error('KILLED')) signal.addEventListener('abort', onAbort) try { const step_1 = await this.function1() // 每步异步执行完成后先检查是否已取消,再继续后续逻辑 if (signal.aborted) return // 注:原示例此处有笔误,function2入参应为step_1而非未定义的step_2 const step_2 = await this.function2(step_1) if (signal.aborted) return const step_3 = await this.function3(step_2) if (signal.aborted) return resolve(await this.function4(step_3)) } finally { // 移除事件监听避免内存泄漏 signal.removeEventListener('abort', onAbort) } }) } // 可选优化:如果function1~function4是你自行实现的逻辑,可以传入signal支持中途取消 // 比如内部使用fetch、fs异步方法时直接传入signal,原生API会自动响应取消 // async function1(signal) { // return fetch('/api/xxx', { signal }) // } } module.exports = Example;
第二步:批量启动任务和统一取消逻辑
const Example = require("./Example.js"); // 全局控制器,所有任务共用同一个取消信号 const globalController = new AbortController() const taskList = [] for (let i = 0; i < 10; i++) { const example = new Example(); // 传入信号,捕获取消状态 const task = example.start(globalController.signal) .catch(err => err.message === 'KILLED' ? `任务${i}已终止` : err) taskList.push(task) } // 需要终止所有任务时调用以下代码即可: // globalController.abort() // 可等待所有任务完成(包括被终止的任务) // await Promise.all(taskList)
方案优势
- 事件驱动触发取消,无需
setInterval轮询,性能开销极低 - 仅需在异步步骤之间加一次状态检查,不需要全量插入检测逻辑,可维护性高
- 符合ECMAScript标准,和所有原生支持取消信号的API(fetch、文件异步操作、流操作等)兼容,可实现正在执行的异步操作中途终止,不会等待整个函数执行完成
- 注意:如果你的
function1~function4内部是CPU密集型同步计算逻辑,受JS单线程特性限制,无法从外部强行终止正在运行的同步代码,需要在内部计算的关键节点插入if (signal.aborted) return的检查逻辑。
内容的提问来源于stack exchange,提问作者Apollo
相关产品推荐
相关产品推荐

