0

So based on 2 StackOverflow answers, what I have understood is:

  1. XHR callback is queued with Macrotasks
  2. Fetch method is queued with Microtasks

So my question is:

  1. Is this true?
  2. If yes, why is it this way? Shouldn't both of them be treated in the same way?
  • 1
    "*Shouldn't both of them be treated in the same way?*" why should they? – VLAZ Oct 24 '22 at 14:24
  • Sorry, if I sound naive but from my perspective, both are network requests that will give back some data. Hence, they should be treated in the same way. – thecoder-elite Oct 24 '22 at 14:31
  • 1
    They are two different APIs. They are allowed to function differently. There is no requirement they be implemented the same. I struggle to think of what difference it would make anyway. There are *maybe* two cases that sort of would be affected: 1. if you *require* micro/macrotasks in order to sequence async tasks correctly. In which case: don't. 2. If having *a lot* of microtasks blocks the UI since UI updates go on the macrotask queue. In which case...again don't? Or space out the processing with a full macrotask tick or something but that should be an edge case. – VLAZ Oct 24 '22 at 14:35

2 Answers2

3

Is this true?

Yes.

When XMLHttpRequest was created there was no microtask queue. Only one - what is now called the macrotask queue.

However, when fetch() was introduced, promises were already in the standard. The result of fetch() is a promise and all effects after a promise resolution are done via the microtask queue:

setTimeout(() => console.log("macrotask done"), 0);          //logged second

Promise.resolve().then(() => console.log("microtask done")); //logged first

Hence resolving the promise from fetch() will also add the subsequent handlers to the microtask queue. Again, it is the one used for the handlers all promises.

If yes, why is it this way? Shouldn't both of them be treated in the same way?

There is no requirement for the two to work the same. Nor would the resolution of these make much of a practical difference in day-to-day code.

Do note that the two are not really the same, either - fetch will resolve as soon as a result is returned before the body of the result is read. Hence why calling .json() or .text() is needed, see Why does .json() return a promise? - calling those methods that will actually process the body. XHR does not have this intermediate step required, its body is processed once it assumes ready state 4 (done).

VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • 1
    Regarding your last paragraph, XHR triggers the `readystatechange` event at intermediate states, which allows for things like progress bars and (I'm guessing) processing an incomplete response. – Barmar Oct 24 '22 at 15:09
  • 1
    I disagree with your first answer. Also "*all promise resolution is done on the microtask queue*" seems wrong, surely in `new Promise(resolve => setTimeout(resolve, 100))` the promise is resolved from a macro task? It's only promise *handlers* that run as micro tasks. – Bergi Oct 24 '22 at 15:55
  • @Bergi Once the macrotask finishes, the resolution of the promise is done as a microtask. Any of the handlers for the promise will be queued there. – VLAZ Oct 24 '22 at 15:57
  • @VLAZ Not sure we agree on what the terminology "resolution of the promise" means. I can assure you that the state of the promise changes during the macro task - and it's queuing the handlers *as microtasks* from the macrotask. – Bergi Oct 24 '22 at 15:59
  • @Bergi I believe we're both referencing the same thing. Perhaps I wasn't really clear enough in my answer. I mean *handling the resolution*. As yes, it does change state, however, the resulting effects after the state change is done via microtasks. – VLAZ Oct 24 '22 at 16:02
  • Thanks, your and @Bergi's answer makes a lot of sense. – thecoder-elite Oct 25 '22 at 17:32
3

Is this true?

No. Re-read the answer your linked:

When the the request response will be received […], the browser will queue a new task which will only be responsible of resolving that Promise, […]

I've emphasised the macrotask for you.

Shouldn't both of them be treated in the same way?

No, why would they? One is a promise API, the other is not. Notice that if you wrap XMLHttpRequest in a promise, you get exactly the same behaviour: the load/readystatechange event (a macro task) resolves a promise, scheduling any promise handler (a micro task).

But ultimately you should ask yourself: does it even matter? You normally shouldn't need to concern yourself with such timing details.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375