如何点击跳过按钮终止含多个await的JavaScript动画函数?
如何通过按钮终止含await的动画进程
JS无法强制终止正在运行的函数,最优雅的方案是用AbortController(现代浏览器原生支持的API)实现协作式中止——让动画函数内部监听中止信号,点击跳过按钮时触发信号,让异步逻辑提前结束。
具体实现步骤
1. 初始化控制器并绑定按钮事件
创建AbortController实例,给跳过按钮绑定中止触发逻辑:
const skipAnimationBtn = document.querySelector("#skip-animation"); const animationController = new AbortController(); // 点击按钮触发中止 skipAnimationBtn.addEventListener('click', () => { animationController.abort(); });
2. 改造动画函数与异步子函数
让动画函数接收signal参数,同时给异步逻辑添加中止支持,有两种实现方式:
方式一:直接给异步子函数添加信号监听
如果是你自己编写的异步动画函数(比如function1),可以直接修改它们支持AbortSignal:
// 改造异步子函数,支持中止信号 async function function1(signal) { // 若信号已中止,直接返回 if (signal.aborted) return; // 绑定中止事件,清理动画资源(定时器、DOM动画等) const cleanup = () => { // 示例:清除动画定时器 // clearTimeout(animationTimer); // 或取消DOM动画:element.getAnimations().forEach(anim => anim.cancel()); }; signal.addEventListener('abort', cleanup); // 原动画逻辑 await new Promise(resolve => { const timer = setTimeout(resolve, 1500); // 中止时同步清除定时器 signal.addEventListener('abort', () => clearTimeout(timer)); }); // 移除监听,避免内存泄漏 signal.removeEventListener('abort', cleanup); } // 改造主动画函数 async function animation(signal) { try { await function1(signal); await function2(signal); function3(); // 同步函数执行时无法中止,只能在执行前后检查状态 await function4(signal); function5(); } catch (err) { // 捕获中止错误,避免控制台报错 if (err.name !== 'AbortError') throw err; } } // 启动动画,传入中止信号 animation(animationController.signal);
方式二:用工具函数简化中止检查(无需修改子函数)
如果不想逐个修改异步子函数,可以写一个工具函数,自动给Promise添加中止逻辑:
// 工具函数:包装Promise,信号中止时立刻拒绝 async function wrapAbortable(promise, signal) { if (signal.aborted) throw new DOMException('动画已跳过', 'AbortError'); return Promise.race([ promise, new Promise((_, reject) => { signal.addEventListener('abort', () => { reject(new DOMException('动画已跳过', 'AbortError')); }); }) ]); } // 主动画函数简化写法 async function animation(signal) { try { await wrapAbortable(function1(), signal); await wrapAbortable(function2(), signal); function3(); await wrapAbortable(function4(), signal); function5(); } catch (err) { if (err.name !== 'AbortError') throw err; } }
关键说明
- 同步函数(比如
function3、function5)执行时无法被中止,只能在执行前后检查signal.aborted状态,决定是否继续后续逻辑。 - 若动画中使用
fetch、ReadableStream等原生API,它们本身支持AbortSignal,直接传入signal即可实现中止。
内容的提问来源于stack exchange,提问作者Isaac Zheng
相关产品推荐
相关产品推荐

