0

I am having a bit of a hard time understanding how javascript asynchronous functions work. In my actual use case, the function in question is a 3rd part API call but a simple setTimeout function is a simpler way to reproduce my problem.

I expect the code infinity loop until the set time function is done and then exit the loop and continue the program. In this example I want/expect the output to be "in set timeout: 5", followed by "out of set timeout: 5" but instead it infinitely loops indicating that the setTimeout function never even runs.

I have also tried without the loop and putting await before setTimeout(function() but then it prints "out of set timeout: 1" followed by "in set timeout: 5".

TLDR: I want my code to use an asynchronous function in a synchronous fashion.

async function doWork() {
  var a = 1
  setTimeout(function() {
    a = 5
    console.log(`in set timeout: ` + a)
  }, 1000)
  i = 0
  while (a == 1) {}

  console.log(`\nout of set timeout: ` + a)
}

doWork()
Omri Attiya
  • 3,917
  • 3
  • 19
  • 35
  • JavaScript is not multithreaded. As soon as it gets to the infinite loop, it will stay there until it finishes (I.e. never). You either want to call a function from the setTimeout or use await or something like that (depending on your case). “Asynchronous function in a synchronous fashion” makes me think await. – DemiPixel Apr 10 '21 at 18:05
  • It would work with `while(a == 1) { await; }` – Jonas Wilms Apr 10 '21 at 18:10
  • " I want my code to use an asynchronous function in a synchronous fashion." that's entirely impossible. – Jonas Wilms Apr 10 '21 at 18:12
  • @JonasWilms had the same idea, tried it; didn't work. I assume the next promise is prioritized over returning to the event queue and executing the function from the timeout. – Thomas Apr 10 '21 at 18:13
  • @thomas in which environment? I think the spec does not define task priority, but the web spec does with it's microtasks/macrotasks (and NodeJS also has something like this) – Jonas Wilms Apr 10 '21 at 18:15
  • @JonasWilms I just copied the snippet to an answer, made the change and ran it. – Thomas Apr 10 '21 at 18:17
  • 2
    Yeah, browsers put Promise resolution into a "microtask queue" and setTimeout callbacks into a "macrotask queue", and microtasks always run before macrotasks. So a macrotask is needed, `await new Promise(r => setTimeout(r, 0))` should do it then. – Jonas Wilms Apr 10 '21 at 18:20
  • 1
    This does what you need: `function doWork(val) { return new Promise ((resolve, reject) => { setTimeout(() => { resolve('in setTimeout:' + val); }, 1000); }); } async function newFunc(){ let a = 5; const res1 = await doWork(a); console.log(res1); a = 1; console.log('out of setTimeout:' + a); } newFunc();` – Dan Sutherland Apr 10 '21 at 18:43

0 Answers0