如何中断当前useEffect执行并启动下一轮渲染的执行?
如何中断useEffect当前执行并在下一次渲染时重启?
问题场景
需要实现这样的逻辑:当useEffect的依赖项更新时,直接中断当前正在执行的异步任务,启动新的任务。示例如下:
... useEffect(() => { SlowFunction(update); }, [update]); setUpdate(1) // 过了一点时间,但SlowFunction(1)还未执行完成 setUpdate(2) // 调用此方法触发useEffect时,停止SlowFunction(1)并执行SlowFunction(2)
可行实现方案
你基于AbortController的实现完全正确,以下是整理后的完整代码:
const [update, setUpdate] = useState(0); const [thisConst, setThisConst] = useState(0); async function SlowFunction(firstParam, paramEtc, { signal } = {}) { while (true) { // 每轮等待2秒 await new Promise((r) => setTimeout(r, 2000)); // 每次执行任务前检查是否已中止,若中止则抛出错误终止函数 signal?.throwIfAborted(); // 继续执行核心任务逻辑 console.log('working on another iteration'); } console.log('Completed!'); return 'some value'; } useEffect(() => { const controller = new AbortController(); const { signal } = controller; (async () => { try { const result = await SlowFunction(update, 'some other value', { signal, }); setThisConst(result); // 注:原代码中的setConst应为setThisConst } catch (ex) { console.log('EXCEPTION THROWN: ', ex); } })(); // useEffect清理函数:依赖项更新时,中止当前运行的异步任务 return () => controller.abort(new Error('Starting next render')); }, [update]);
关键逻辑说明
- AbortController 信号机制:通过浏览器原生的
AbortController创建中止信号,将信号传递给异步函数SlowFunction,实现任务的可中断性。 - 任务检查点:在异步函数的每轮循环等待结束后,调用
signal.throwIfAborted()检查中止状态,若已触发中止则直接抛出错误,终止后续代码执行。 - useEffect 清理时机:当
update更新触发新的useEffect执行时,旧的useEffect会先执行返回的清理函数,调用controller.abort()触发中止信号,中断旧的SlowFunction进程。
内容的提问来源于stack exchange,提问作者Jackson Stone
相关产品推荐
相关产品推荐

