簡體   English   中英

Javascript 等待循環完成

[英]Javascript wait for loop to finish

我想等到 for 循環完成后再繼續我的 function。 我似乎無法讓它工作。 Hello 總是在 for 循環結束之前被記錄。 為什么會這樣,以及只有在 for 循環完成后才能運行的方法。 我需要等待 for 循環完成,然后在 function 中繼續,但在 for 循環之外。

對於一直關閉這個問題的人來說,這是不同的。 我想知道如何等到 for 循環完成,然后執行代碼。 未在 for 循環中設置超時。 謝謝。

function doMergeAnimations(animations){
    for (let i = 0; i < animations.length; i++) {
        const arrayBars = document.getElementsByClassName('array-bar');
        const isColorChange = i % 3 !== 2;
        if (isColorChange) {
            const [barOneIdx, barTwoIdx] = animations[i];
            const barOneStyle = arrayBars[barOneIdx].style;
            const barTwoStyle = arrayBars[barTwoIdx].style;
            const color = i % 3 === 0 ? INITCOLOR : SWAPCOLOR;
            setTimeout(() => {
            barOneStyle.backgroundColor = color;
            barTwoStyle.backgroundColor = color;
            }, i * animationSpeed);
        } else {
            setTimeout(() => {
            const [barOneIdx, newHeight] = animations[i];
            const barOneStyle = arrayBars[barOneIdx].style;
            barOneStyle.height = `${newHeight}px`;
            }, i * animationSpeed);
        }
    }
    console.log("Hello")
}

如果這里的實際目標是隨着時間的推移觸發一系列事件,那么您不能使用for循環來構造執行,這不適用於異步事件。 你必須重組它:

function doMergeAnimations(animations){
    let events = [ ];
    for (let i = 0; i < animations.length; i++) {
        const arrayBars = document.getElementsByClassName('array-bar');
        const isColorChange = i % 3 !== 2;
        if (isColorChange) {
            const [barOneIdx, barTwoIdx] = animations[i];
            const barOneStyle = arrayBars[barOneIdx].style;
            const barTwoStyle = arrayBars[barTwoIdx].style;
            const color = i % 3 === 0 ? INITCOLOR : SWAPCOLOR;
            events.push(() => {
            barOneStyle.backgroundColor = color;
            barTwoStyle.backgroundColor = color;
            });
        } else {
            events.push(() => {
            const [barOneIdx, newHeight] = animations[i];
            const barOneStyle = arrayBars[barOneIdx].style;
            barOneStyle.height = `${newHeight}px`;
            });
        }
    }

    let timer = setInterval(() => {
        let fn;

        if (fn = events.shift()) {
          fn();
        }
        else {
          clearInterval(timer);
        }
    }, animationSpeed);

    console.log("Hello");
}

就像在這個快速演示中一樣:

 function arrayPopper(array, delay) { let events = [ ]; array.forEach(e => { events.push(() => console.log(e)); }) let timer = setInterval(() => { let fn; if (fn = events.shift()) { fn(); } else { clearInterval(timer); } }, delay); events.push(() => console.log("Hello")); } arrayPopper([ 1, 2, 3, 4, 5, 6, 'done' ], 500);

您甚至可以通過添加以下內容輕松地 Promisify:

async function doMergeAnimations(animations) {
  return new Promise((resolve, _reject) => {
    let events = [ ];

    // Same code...

    events.push(resolve);
  });
}

這意味着您現在可以執行以下操作:

// Chained promise
doMergeAnimations(...).then(() => console.log('Done!'));

// async function
await doMergeAnimations(...);
console.log('Done!');

問題不在於循環,問題在於您循環中所做的事情。 您正在使用setTimeout調用異步操作,這一切都在以后發生。 如果您想等待這些完成,那么您可能希望將setTimeout包裝在Promise中,然后等待它。

你可以用類似的東西包裝它:

const setAwaitableTimeout = async (func, delay) =>
  new Promise((resolve) => setTimeout(() => {
    func();
    resolve();
  }), delay);

然后你可以讓你的 function async並使用它而不是setTimeout 哪個有額外的好處,您不需要在延遲中乘以i來模仿等待行為:

async function doMergeAnimations(animations) {
  for (let i = 0; i < animations.length; i++) {
    // existing code, then...
    await setAwaitableTimeout(() => {
      barOneStyle.backgroundColor = color;
      barTwoStyle.backgroundColor = color;
    }, animationSpeed);
    // the rest of your code
  }
  console.log("Hello");
}

如果您將setTimeouts()包裝在 Promise 中,您可以控制結果。

在這里,每個 animation 都放置在 Promise object 內,並且 ZB321DE3BDC299EC807E9F795D7Dmises9DEEBZ 被推入 Pro 數組每個setTimeout()然后在 animation 完成時調用resolve()

循環完成后,使用Promise.all()等待陣列中每個 Promise 完成。 最后,在 Promise 的 .then .then()內部是“循環完成”(概念上)。

function doMergeAnimations(animations) {
  const animPromises = [];
  for (let i = 0; i < animations.length; i++) {
    const arrayBars = document.getElementsByClassName('array-bar');
    const isColorChange = i % 3 !== 2;
    if (isColorChange) {
      const [barOneIdx, barTwoIdx] = animations[i];
      const barOneStyle = arrayBars[barOneIdx].style;
      const barTwoStyle = arrayBars[barTwoIdx].style;
      const color = i % 3 === 0 ? INITCOLOR : SWAPCOLOR;
      animPromises.push(new Promise(resolve => {
          setTimeout(() => {
            barOneStyle.backgroundColor = color;
            barTwoStyle.backgroundColor = color;
            resolve();
          }, i * animationSpeed)
        });
      }
      else {
        animPromises.push(new Promise(resolve => {
            setTimeout(() => {
              const [barOneIdx, newHeight] = animations[i];
              const barOneStyle = arrayBars[barOneIdx].style;
              barOneStyle.height = `${newHeight}px`;
              resolve();
            }, i * animationSpeed)
          });
        }
      }
      Promise.all(animPromises).then(() => console.log("Hello"));
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM