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
Without timeout and async await:
Input
Output
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);
}
}