我怎么能只有一个功能 运行 在另一个功能完成时才能使用? (for 循环中的 setTimeout)

How can I have one function run only when the other has finished ? (setTimeout within for-loop)

我正在尝试找到一种简单、直接的方法,以便在第一个函数完成后将第二个函数转至 运行。我已经尝试了一些我在网上遇到的建议,但由于它们在 for 循环中具有 setTimeouts,因此这些特定函数的运行方式似乎有所不同。到目前为止,我尝试过的所有操作都会导致第二个功能在第一个功能完成之前 运行(更新页面上的某些颜色样式)。

const [VisitedNodes, setVisitedNodes] = useState([]);  
const [ShortestPath, setShortestPath] = useState([]);

// runs first
function drawVisitedNodes() {
  for (let i = 0; i < VisitedNodes.length; i++) {
    const node = VisitedNodes[i];
    setTimeout(() => {
        document.getElementById(`${node.x}-${node.y}`).className =
          "node-visited";
    }, i);
  }
  drawShortestPath();
}

// runs second
function drawShortestPath() {
  for (let i = 0; i < ShortestPath.length; i++) {
    const node = ShortestPath[i];
    setTimeout(() => {
        document.getElementById(`${node.x}-${node.y}`).className =
          "node-shortPath";

    }, i * 10);
  }
}

<button 
    onClick={drawVisitedNodes}>Visualize
</button>

您可以使用await等待所有逻辑完成

像这样

async function foo() {
    for (let i = 0; i < VisitedNodes.length; i++) {
        const node = VisitedNodes[i];
        setTimeout(() => {
            document.getElementById(`${node.x}-${node.y}`).className =
              "node-visited";
        }, i);
    }
}

function drawVisitedNodes() {
  await foo();
  drawShortestPath();
}

// runs second
function drawShortestPath() {
  for (let i = 0; i < ShortestPath.length; i++) {
    const node = ShortestPath[i];
    setTimeout(() => {
        document.getElementById(`${node.x}-${node.y}`).className =
          "node-shortPath";

    }, i * 10);
  }
}

您可以尝试这样的操作:

const [VisitedNodes, setVisitedNodes] = useState([]);  
const [ShortestPath, setShortestPath] = useState([]);

// runs first
function drawVisitedNodes() {
  let x= 0;
  for (let i = 0; i < VisitedNodes.length; i++) {
    const node = VisitedNodes[i];
    setTimeout(() => {
        document.getElementById(`${node.x}-${node.y}`).className =
          "node-visited";
    }, i);
    x++;
  }
  setTimeout(() =>  drawShortestPath(), x);
}

// runs second
function drawShortestPath() {
  for (let i = 0; i < ShortestPath.length; i++) {
    const node = ShortestPath[i];
    setTimeout(() => {
        document.getElementById(`${node.x}-${node.y}`).className =
          "node-shortPath";

    }, i * 10);
  }
}

<button 
    onClick={drawVisitedNodes}>Visualize
</button>

这会给第二个函数的执行增加一些延迟。多少时间? x 会告诉你,因为在 for 的末尾会是 VisitedNodes.length。是的,你也可以这样做:

setTimeout(() =>  drawShortestPath(), VisitedNodes.length)

所以,为了让您了解为什么会这样,我将给您举下一个示例:

  • VisitedNodes state 是一个包含 4 个元素的数组。
  • ShortestPath state 是一个包含 2 个元素的数组。
  • 单击按钮将导致执行 drawVisitedNodes() 函数。

在您的情况下,执行将是:

  1. setTimeout(() => codeForNode1, 0)
  2. setTimeout(() => codeForNode2, 1)
  3. setTimeout(() => codeForNode3, 2)
  4. setTimeout(() => codeForNode4, 3)
  5. drawShortestPath()

但是,由于 setTimeout 的原因,实际执行将是:

  1. drawShortestPath()
  2. codeForNode1
  3. codeForNode2
  4. codeForNode3
  5. codeForNode4

根据我的建议,您的代码将保持顺序。让我们看看:

  1. setTimeout(() => codeForNode1, 0)
  2. setTimeout(() => codeForNode2, 1)
  3. setTimeout(() => codeForNode3, 2)
  4. setTimeout(() => codeForNode4, 3)
  5. setTimeout(() => drawShortestPath(), 4)

最终执行将是:

  1. codeForNode1
  2. codeForNode2
  3. codeForNode3
  4. codeForNode4
  5. drawShortestPath()

在评论中,您问我为什么使用实际数字不起作用。好吧,我的回答是,这取决于您拥有的 VisitedNodes 数量。使用我刚刚给你的例子,如果你使用 x < 4 它将不起作用,因为你试图在 codeForNode4 执行之前执行 drawShortestPath() 函数,所以你正在混合执行在这种情况下。但是,如果您设置 x ≥ 4,它将按您的预期工作。