You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:10:04