如何使用jQuery/Promise实现动画队列循环,待前序动画完成后执行下一个
动画队列串行执行优化方案
原实现存在的问题
- 每次新增状态入队时都会遍历整个队列重建promise链,已入队的任务会被重复绑定回调,存在动画重复执行的隐患
- 在reduce遍历过程中调用
shift()修改原队列,会打乱遍历索引,极端场景下会出现状态漏执行、执行顺序错乱的问题 - 每次执行动画都重复查询DOM节点,存在不必要的性能开销
优化后实现
let animation_queue = []; // 标记当前是否有动画正在执行 let isAnimating = false; function runNextAnimation(box) { // 队列空则重置状态退出 if (animation_queue.length === 0) { isAnimating = false; return; } isAnimating = true; const currentState = animation_queue.shift(); // 串行执行淡出+淡入动画 box.find("[class*='btn__state__']").fadeOut(500).promise() .then(() => { return box.find(`[class*='btn__state__${currentState}']`).fadeIn(500).promise() }) .then(() => { // 当前动画执行完毕,自动执行下一个 runNextAnimation(box); }) } function button_state(form, state) { const box = $(form).find('.btn_state_box'); animation_queue.push(state); // 无动画运行时主动启动队列 if (!isAnimating) { runNextAnimation(box); } }
方案优势
- 仅在动画全部执行完成后才取下一个任务,严格保证动画按入队顺序串行执行,完全匹配ajax状态返回顺序不确定的场景
- 无需每次入队都重建promise链,执行逻辑更简洁,运行性能更高
- 避免了原实现中队列修改和遍历并发导致的状态错乱问题
注:
runNextAnimation的递归调用是在动画结束的异步回调中触发,不属于同步递归,不会出现栈溢出问题。
内容的提问来源于stack exchange,提问作者Necromant
相关产品推荐
相关产品推荐

