Here is my code to print input data in the order of the timer
values. I used promises:
let a = [
{ data: 1000, timer: 3000 },
{ data: 2000, timer: 2000 },
{ data: 3000, timer: 1000 },
]
const sleep = (m, d) =>
new Promise((r,d) => setTimeout(r, m)).then((res) => {
console.log(d);
});
a.map(async (item) => {
await sleep(item.timer, item.data);
});
The output should be
1000
2000
3000
but in the above attempt I am getting
3000
2000
1000
Why is it like that?
The code is doing what is expected, but you are getting confused with the values for data
and timer
: these are the same values (1000, 2000, 3000), but ordered in opposite directions. One can easily interpret the output data as a timeout. When the output happens in increasing order of timer
, then the output will be decreasing when you output the data
properties (instead of the timer
properties).
One way to clarify what happens is to not just print the data, but the whole object. Then it is clear that the objects are output in the correct order.
Some unrelated remarks:
.map
when you are not creating an array.async/await
when you are not doing anything after that await
, nor with the promise that is returned.r
and d
, and avoid shadowing variables by using the same name for different scoped variables (like you have d
).I have applied those remarks to the code, but the essence is in changing the second argument that is passed to sleep
and the formatting in console.log
let arr = [
{ data: 1000, timer: 3000 },
{ data: 2000, timer: 2000 },
{ data: 3000, timer: 1000 },
]
const sleep = (ms, obj) =>
new Promise(resolve => setTimeout(resolve, ms)).then(() => {
console.log(JSON.stringify(obj));
});
arr.forEach(item => sleep(item.timer, item));
Another remark is to not use console.log
in such a generic function as sleep
. It is better to get that console.log
out of there, and place it in the main loop. I did not do this in the above code, as that would hide too much what the core solution was to your question, but I provide it here as illustration:
let arr = [
{ data: 1000, timer: 3000 },
{ data: 2000, timer: 2000 },
{ data: 3000, timer: 1000 },
]
const sleep = (ms, obj) => new Promise(resolve => setTimeout(resolve, ms));
arr.forEach(item => sleep(item.timer).then(() => console.log(item)));
Both in your code and this code, all three timers start at about the same time, before any asynchronous code gets executed. So the output of the object with timer
equal to 1000 is expected to happen approximately 1 second after the start of the program, the one with 2000 is expected approximately 2 seconds after the start of the program, and the one with timer
3000 is expected to be output about 3 seconds after the start.