ReactJS中如何在一个函数执行完成后再执行另一个函数
问题:动画函数无法按顺序执行
点击按钮时需要先执行第一个动画函数animate(nodesVisitedInOrder),完成后再执行第二个animate(path),但目前两个函数会同时运行。尝试用setTimeout延迟第二个函数执行,效果也不符合预期。
当前按钮代码:
<button onClick={() => { animate(nodesVisitedInOrder); animate(path); // 希望这个函数在前一个执行完成后再运行 }} >
尝试过的代码:
<button onClick={() => { animate(nodesVisitedInOrder); setTimeout(() => animate(path), 1000); }} >
动画函数代码:
const animate = (nodes) => { for (let i = 0; i < nodes.length; i++) { setTimeout(() => { const node = nodes[i]; setTable((prev) => { const newArray = []; for (var i = 0; i < prev.grid.length; i++) { newArray[i] = prev.grid[i].slice(); } return { ...prev, grid: newArray.map((items) => items.map((item) => { const { row, col } = item.pos; return row === node.row && col === node.col ? { ...item, isAnimate: !item.isAnimate } : item; }) ), }; }); }, 10 * i); } };
解决方案
问题出在animate函数本身是同步执行的,里面的setTimeout是异步任务,调用animate后函数会立刻结束,导致两个动画的定时器同时触发。要解决这个问题,需要让animate返回一个Promise,等所有内部定时器执行完成后再resolve,这样就能用async/await控制执行顺序。
步骤1:修改animate函数为Promise版本
const animate = (nodes) => { return new Promise((resolve) => { if (nodes.length === 0) { resolve(); return; } for (let i = 0; i < nodes.length; i++) { setTimeout(() => { const node = nodes[i]; setTable((prev) => { // 简化数组拷贝写法 const newArray = prev.grid.map(row => [...row]); return { ...prev, grid: newArray.map((items) => items.map((item) => { const { row, col } = item.pos; return row === node.row && col === node.col ? { ...item, isAnimate: !item.isAnimate } : item; }) ), }; }); // 最后一个节点动画执行完成后,标记整个动画结束 if (i === nodes.length - 1) { resolve(); } }, 10 * i); } }); };
步骤2:修改按钮的onClick为async函数
<button onClick={async () => { await animate(nodesVisitedInOrder); await animate(path); }} > 执行动画 </button>
说明
- 让
animate返回Promise,当最后一个定时器执行完成后调用resolve,表示整个动画序列结束。 - 使用
async/await语法,确保第一个animate的Promise resolve后,再执行第二个animate。 - 优化了数组拷贝的写法,用
map(row => [...row])替代原循环,代码更简洁。
内容的提问来源于stack exchange,提问作者Grease
相关产品推荐
相关产品推荐

