Search code examples
javascriptasynchronouscallbackes6-promiseecmascript-2016

setTimeout performing before a task in micro task queue (Job queue)


I'm having trouble understanding why my code below logs the following in order: "end" "timeout done" "promise"

I assumed that "promise" would log before "timeout done" since it has a priority over callback queue task (setTimeout). My assumption after this observation is that until .then is called, the promise does not enqueue its task since it's not ready yet, and thus allows setTimeout to perform in the callback queue to be performed first. Is this correct?

const sampleFunction = function(e) {
  setTimeout(() => console.log('timeout done'), 0)
  const data = fetch(`https://jsonplaceholder.typicode.com/comments/1`)
  .then(response => {
    return response.json();
  })
  .then(json => {
    /*doSomething*/
    console.log('promise')
  });
  console.log('end')
}

Solution

  • Your console.log('promise') has to wait until your fetch().then() is done which involves a networking operation to another host (and thus non-zero time).

    Your setTimeout() only has to wait until sampleFunction() returns and you get back to the event queue. So, since the fetch().then() is non-blocking and takes non-zero amount of time, when you first get back to the event queue, only the setTimeout() is ready to go. The networking operation will still be in process in the background.

    So, this isn't a matter of prioritization. It's a matter of completion order. The setTimeout() inserts its completion event into the event queue long before the fetch() promise is resolved.

    Perhaps you didn't realize that fetch() is non-blocking and calling it just initiates the operation and then your code execution continues after that?

    In the console, you should see:

    end
    timeout done
    promise
    

    As long as your fetch() doesn't have any errors.