-1

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?

trincot
  • 317,000
  • 35
  • 244
  • 286
  • no, the order is correct ... you sleep 1000 before outputting 3000, 2000 before outputting 2000 and waiting 3000 before outputting 1000 ... the sleeps don't wait for each other – Jaromanda X Sep 07 '22 at 03:44
  • That's not how `setTimeout` works. `setTimeout` expects to be handed a function to be called when the time expires. Were you thinking of `delay`? – Tim Roberts Sep 07 '22 at 03:47
  • If you are trying to print in order after the timer, I would use setTimeout and wait for the response before setting the next timer. – skyCode Sep 07 '22 at 03:51
  • @TimRoberts - `r` IS a function – Jaromanda X Sep 07 '22 at 03:55
  • You're right. My bad. Perhaps this can help: https://stackoverflow.com/questions/39538473/using-settimeout-on-promise-chain – Tim Roberts Sep 07 '22 at 04:01

1 Answers1

0

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:

  • don't use .map when you are not creating an array.
  • don't use async/await when you are not doing anything after that await, nor with the promise that is returned.
  • don't use meaningless variable names like 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.

trincot
  • 317,000
  • 35
  • 244
  • 286