To start, I realize that I can use async/await or promise chains to accomplish this. I’m trying to understand why the following specifically doesn’t work.
My understanding of this code is that it should make the p1
fetch, which in turn sends the HTTP request to the event queue and immediately starts making the request async, run the for
loop (blocking, code below won’t run until the for
completes), then make the p2
fetch (by this time I would expect that the p1
fetch would be complete), then we get to the p1.then
and the p2.then
. Since I gave the p1
a huge head start in the form of the for
loop, I would expect that we almost always would print 0
. But that is not the case. It seems completely indeterministic. I understand that there are network conditions, but I would think that the head start given by the for
loop would be enough to deterministically return 0
.
This makes me feel like I have a gap in my understanding. I’m wondering why this works this way?
let x = 1;
let url = "https://www.google.com";
let p1 = fetch(url);
for (let i = 0; i < 1000000000; i++) {}
// Is it possible to ensure that the promise `p1` gets resolved earlier than `p2`? (By blocking the code here) Not working with the `for` loop.
let p2 = fetch(url);
p1.then(() => {
x = 0;
});
p2.then(() => {
x = x * 1;
// Because of the race condition between `p1` and `p2`, the value of `x` is indeterministic.
console.log(x);
});
I tried increasing the iterations of the for
loop and still got an indeterministic result.
2
Answers
If you want the operations in your two
.then()
s to be executed in a certain order you should use something likePromise.all()
to enforce both promises to be fulfilled before the actual processing of the data will start in the predefined order:fetchSequentially ensures that p1 completes before p2 starts, and the blocking for loop occurs after p1 has been resolved. This way, you eliminate the race condition between p1 and p2