Home > OS >  How to implement time intervals during execution of nested loops
How to implement time intervals during execution of nested loops

Time:01-06

I try to make an algorithm visualization project - right now I am implementing visualization of bubble-sort - I've got an array of arrays in which each outer array represents one iteration of the algorithm, and each inner array consists of boolean values - swap or no swap neighboring elements in the collection - I have algorithm ready, and sorting is done correctly, right now I wanted to introduce time delays between each swap - as it is visualization program I want the user to see actually what's going on. Here I stumbled upon a problem - I wanted to use async await with setTimeout but apparently I lack knowledge (I mostly work with java) - columns are not sorted correctly - I would say that setTimeout is incorrectly scheduled in parallel for different iterations, but I am not sure. Code of mine:

async function visualiseAlgorithm(responseFromServer) {
    for (const iteration of responseFromServer.data) {
        await displayIteration(iteration.swapsRecord);
    }
}

async function displayIteration(swapsForIteration) {
    let idx = 0;
    for (const shouldSwap of swapsForIteration) {
        await drawColumns(shouldSwap, idx  ).then(res => {
            context.clearRect(0, 0, canvas.width, canvas.height);
            drawBaseLine();
            columnsArray.forEach(column => column.draw());
        });
    }
}

function drawColumns(toSwap, index){
    return new Promise(resolve => setTimeout(() => {
        if(index > 1) columnsArray[index - 1].setColor("grey");
        let color;
        if(toSwap){
            color = "red";
            let temp = columnsArray[index].getHeight();
            columnsArray[index].setHeight(columnsArray[index   1].getHeight());
            columnsArray[index   1].setHeight(temp);
        }

    }, 100))
}

Results:

With timeout and async await:

Input:

Output

enter image description here

Without timeout and async await:

Input

enter image description here

Output

enter image description here

As requested: I post response from the server:

Array(37) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
0: Object { swapsRecord: [], collection: (45) […] }
1: Object { swapsRecord: (44) […], collection: (45) […] }
2: Object { swapsRecord: (44) […], collection: (45) […] }
3: Object { swapsRecord: (44) […], collection: (45) […] }
4: Object { swapsRecord: (44) […], collection: (45) […] }
5: Object { swapsRecord: (44) […], collection: (45) […] }
6: Object { swapsRecord: (44) […], collection: (45) […] }
7: Object { swapsRecord: (44) […], collection: (45) […] }
8: Object { swapsRecord: (44) […], collection: (45) […] }
9: Object { swapsRecord: (44) […], collection: (45) […] }
10: Object { swapsRecord: (44) […], collection: (45) […] }
11: Object { swapsRecord: (44) […], collection: (45) […] }
12: Object { swapsRecord: (44) […], collection: (45) […] }
13: Object { swapsRecord: (44) […], collection: (45) […] }
14: Object { swapsRecord: (44) […], collection: (45) […] }
15: Object { swapsRecord: (44) […], collection: (45) […] }
16: Object { swapsRecord: (44) […], collection: (45) […] }
17: Object { swapsRecord: (44) […], collection: (45) […] }
18: Object { swapsRecord: (44) […], collection: (45) […] }
19: Object { swapsRecord: (44) […], collection: (45) […] }
20: Object { swapsRecord: (44) […], collection: (45) […] }
21: Object { swapsRecord: (44) […], collection: (45) […] }
22: Object { swapsRecord: (44) […], collection: (45) […] }
23: Object { swapsRecord: (44) […], collection: (45) […] }
24: Object { swapsRecord: (44) […], collection: (45) […] }
25: Object { swapsRecord: (44) […], collection: (45) […] }
26: Object { swapsRecord: (44) […], collection: (45) […] }
27: Object { swapsRecord: (44) […], collection: (45) […] }
28: Object { swapsRecord: (44) […], collection: (45) […] }
29: Object { swapsRecord: (44) […], collection: (45) […] }
30: Object { swapsRecord: (44) […], collection: (45) […] }
31: Object { swapsRecord: (44) […], collection: (45) […] }
32: Object { swapsRecord: (44) […], collection: (45) […] }
33: Object { swapsRecord: (44) […], collection: (45) […] }
34: Object { swapsRecord: (44) […], collection: (45) […] }
35: Object { swapsRecord: (44) […], collection: (45) […] }
36: Object { swapsRecord: (44) […], collection: (45) […] }

Objects in the array consists of: (the collection array is redundant and not used - I plan to delete it)

Object { swapsRecord: (44) […], collection: (45) […] }
collection: Array(45) [ 61, 53, 35, … ]
swapsRecord: Array(44) [ false, true, true, … ]
0: false
1: true
​​​2: true
​​​3: false
​​​4: true
​​​5: true
​​​6: true
​​​7: false
​​​8: true
​​​9: true
​​​10: true
​​​11: true
​​​12: true
​​​13: true
​​​14: true
​​​15: true
​​​16: true
​​​17: true
​​​18: true
​​​19: true
​​​20: true
​​​21: true
​​​22: true
​​​23: true
​​​24: true
​​​25: true
​​​26: true
​​​27: true
​​​28: true
29: true
​​​30: true
​​​31: true
​​​32: true
​​​33: true
​​​34: true
​​​35: true
​​​36: true
​​​37: true
​​​38: true
​​​39: true
​​​40: false
​​​41: true
​​​42: true
​​​43: true
​​​length: 44

CodePudding user response:

You need to resolve the promise or it wouldn't do the following stuff. Without it, your loop will stay the first step.

That's the reason why the output is the same as the input.

async function visualiseAlgorithm(responseFromServer) {
    for (const iteration of responseFromServer.data) {
        await displayIteration(iteration.swapsRecord);
    }
}

async function displayIteration(swapsForIteration) {
    let idx = 0;
    for (const shouldSwap of swapsForIteration) {
        await drawColumns(shouldSwap, idx  ).then(res => {
            context.clearRect(0, 0, canvas.width, canvas.height);
            drawBaseLine();
            columnsArray.forEach(column => column.draw());
        });
    }
}

function drawColumns(toSwap, index){
    return new Promise(resolve => setTimeout(() => {
        if(index > 1) columnsArray[index - 1].setColor("grey");
        let color;
        if(toSwap){
            color = "red";
            let temp = columnsArray[index].getHeight();
            columnsArray[index].setHeight(columnsArray[index   1].getHeight());
            columnsArray[index   1].setHeight(temp);
        }
        // this is the point
        resolve()
    }, 100))
}

For more information https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

CodePudding user response:

You can add a sleep function like this. And, await it whenever you want a delay. This will avoid the superfluous async and Promise wrappers in existing drawColumns function

// https://stackoverflow.com/a/47092642
async function sleep(sec) {
  return new Promise(resolve => setTimeout(resolve, sec));
}

async function visualiseAlgorithm(responseFromServer) {
  for (const iteration of responseFromServer.data) {
    await displayIteration(iteration.swapsRecord);
  }
}

async function displayIteration(swapsForIteration) {
  let idx = 0;
  for (const shouldSwap of swapsForIteration) {
    await sleep(100) // <-- add this whenever you want a delay

    drawColumns(shouldSwap, idx  )
    context.clearRect(0, 0, canvas.width, canvas.height);
    drawBaseLine();
    columnsArray.forEach(column => column.draw());
  }
}

function drawColumns(toSwap, index) {
  if (index > 1) columnsArray[index - 1].setColor("grey");
  let color;
  if (toSwap) {
    color = "red";
    let temp = columnsArray[index].getHeight();
    columnsArray[index].setHeight(columnsArray[index   1].getHeight());
    columnsArray[index   1].setHeight(temp);
  }
}
  • Related