简体   繁体   中英

How to set a timeout between each iteration in Javascript?

I am trying to set a timeout(wait time) between each call of drawLines() inside a setTimeout() in a while-loop.

while(i < j){
            while(i < lastElIndex && array[i] < pivot){
                const iCopy = i;
                const lastCopy = lastElIndex;
                i++;
                const arrCopy = array.slice();
                setTimeout(() => {
                    drawLines(arrCopy, iCopy, -1, lastCopy, -1);
                });
            }

            while(j > firstElIndex && array[j] >= pivot){
                const jCopy = j;
                const firstCopy = firstElIndex;
                j--;
                const arrCopy = array.slice();
                setTimeout(() => {
                    drawLines(arrCopy, -1, jCopy,-1, firstCopy);
                });
            }

I already tried setting the wait time like this

setTimeout(() => {drawLines(arrCopy, iCopy, -1, lastCopy, -1);}, 1000);

...but the timeout happens before the calling drawLines() repeatedly without waiting between calls.

I also tried

setTimeout(async() => {
           drawLines(arrCopy, iCopy, -1, lastCopy, -1);
           await sleep(1000);
});

...with

function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

...but nothing happened

Here is the whole function:

function quickSort(arr, firstElIndex, lastElIndex){
    let array = arr;
    let currentIndex = 0;
    function partition(firstElIndex, lastElIndex) {
        let i = firstElIndex;
        let j = lastElIndex;
        let pivot = array[lastElIndex];
        while(i < j){
            while(i < lastElIndex && array[i] < pivot){
                const iCopy = i;
                const lastCopy = lastElIndex;
                i++;
                const arrCopy = array.slice();
                setTimeout(() => {
                    drawLines(arrCopy, iCopy, -1, lastCopy, -1);
                });
            }

            while(j > firstElIndex && array[j] >= pivot){
                const jCopy = j;
                const firstCopy = firstElIndex;
                j--;
                const arrCopy = array.slice();
                setTimeout(() => {
                    drawLines(arrCopy, -1, jCopy,-1, firstCopy);
                });
            }

            if(i < j){
                array.swap(i, j);
            }
        }
        if(array[i] > pivot){
            array.swap(i, lastElIndex);
        }
        return i;
    }
    if(firstElIndex < lastElIndex){
        currentIndex = partition(firstElIndex, lastElIndex);
        quickSort(array, firstElIndex, currentIndex - 1);
        quickSort(array, currentIndex + 1, lastElIndex);
    }
    setTimeout(() => {drawLines(array, -1, -1);}, 1000);
}

And here is drawLines() :

function drawLines(arr, x, y, rightPivot, leftPivot){
    let array = arr.slice();
    let container = document.getElementById("centerContent");
    let line = undefined;
    container.innerHTML = '';
    for(let i = 0; i < array.length; i++){
        let my_length = (array[i]/6.7).toString() + "vw";line = document.createElement("div");
        line.className = "line";
        if(i === x || i === y){
            line.style.borderLeft = (1/7).toString() + "vw solid red";
        }
        else if(i === rightPivot){
            line.style.borderLeft = (1/7).toString() + "vw solid aqua";
        }
        else if(i === leftPivot){
            line.style.borderLeft = (1/7).toString() + "vw solid orange";
        }
        else{
            line.style.borderLeft = (1/7).toString() + "vw solid black";
        }        
        line.style.height = my_length;
        container.appendChild(line);
    }
}

I apoligize if the question is poorly structured. It's the my first one. Many thanks in advance.

It sounds like you just want a delay to happen before the line is drawn and also before the loop continues. Using async/await can do that for you fairly easily. This is a structure you can use:

// to use await you must define the function to be async
async function partition(firstElIndex, lastElIndex) {
  let i = firstElIndex;
  let j = lastElIndex;
  let pivot = array[lastElIndex];
  while(i < j){
    while(i < lastElIndex && array[i] < pivot){
      const iCopy = i;
      const lastCopy = lastElIndex;
      i++;
      const arrCopy = array.slice();
      // this line pauses execution for 1 second
      await new Promise(resolve => setTimeout(resolve, 1000);
      drawLines(arrCopy, iCopy, -1, lastCopy, -1);
    }

    while(j > firstElIndex && array[j] >= pivot){
      const jCopy = j;
      const firstCopy = firstElIndex;
      j--;
      const arrCopy = array.slice();
      // this line pauses execution for 1 second
      await new Promise(resolve => setTimeout(resolve, 1000);
      drawLines(arrCopy, -1, jCopy,-1, firstCopy);
    }
    if(i < j){
      array.swap(i, j);
    }
    return i;
  }
}

and since partition is now an async function you need to do this when calling it:

if(firstElIndex < lastElIndex){
  currentIndex = await partition(firstElIndex, lastElIndex);
  quickSort(array, firstElIndex, currentIndex - 1);
  quickSort(array, currentIndex + 1, lastElIndex);
}

That requires that quickSort is also and async function which means it returns a Promise object that can be either waited for too, or use .then to know when it's complete.

The first thing is that the setTimeout needs a 2nd parameter with the amount of time to wait, so written like this:

setTimeout(() => {
  drawLines(arrCopy, iCopy, -1, lastCopy, -1);
});

will not wait for any amount of time, unless you pass it a 2nd argument like:

setTimeout(() => {
  drawLines(arrCopy, iCopy, -1, lastCopy, -1);
}, 500);

I think you where on the correct path when creating that sleep function; indeed it wouldn't work when running the timeout inside the loop. But there's no need to return a Promise. Just try:

function sleep(callback, ...callbackParameters) {
  setTimeout(() => callback(...callbackParameters), 500)  // remember your timer
}

And then pass whatever function you want to run after the timeout to your sleep function like: sleep(drawLines, arrCopy, iCopy, -1, lastCopy, -1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM