starkk92
starkk92

Reputation: 5924

How to predict Async nature of the Promises

I have a sample piece of code where I could not predict the flow of the code.

var x = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve([1, 2, 3]);
    }, 0);
  });
};

x().then((val) => {
  console.log(val);
}).catch((err) => {
  console.log(err.message);
});

console.log("hello");

for (var i = 0; i < 10; i++) {
  console.log(i);
}

var y = Promise.all([Promise.resolve(1), Promise.reject(Error("err"))]);

y.then((arr) => {
    console.log(arr);
  })
  .catch((err) => {
    console.log(err);
  });

Promise.resolve('ta-da!')
  .then((result) => {
    console.log('Step 2 received ' + result);
    return 'Greetings from step 2';
  })
  .then((result) => {
    console.log('Step 3 received ' + result);
  })
  .then((result) => {
    console.log('Step 4 received ' + result);
    return Promise.resolve('fulfilled value');
  })
  .then((result) => {
    console.log('Step 5 received ' + result);
    return Promise.resolve();
  })
  .then((result) => {
    console.log('Step 6 received ' + result);
  });

the logs are in the following order:

"hello"
0
1
2
3
4
5
6
7
8
9
"Step 2 received ta-da!"
"Step 3 received Greetings from step 2"
"err"
"Step 4 received undefined"
"Step 5 received fulfilled value"
"Step 6 received undefined"
[1, 2, 3]

The for loop is getting executed as expected. The setTimeout() is working as expected and the promise is fulfilled after the event loop.

The other 2 promises are getting collided. I was expecting the promises will be fulfulled immediately in syncronously and the result would be

"hello"
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    "err"
    "Step 2 received ta-da!"
    "Step 3 received Greetings from step 2"
    "Step 4 received undefined"
    "Step 5 received fulfilled value"
    "Step 6 received undefined"
    [1, 2, 3].

Even if the promises are resolved async.How are they collided.

Screenshot attached.

enter image description here

Upvotes: 3

Views: 132

Answers (2)

Bergi
Bergi

Reputation: 664579

You've got three separate promise chains in your code:

  1. the one that starts with x() and takes the longest because of the timeout
  2. the one that starts with y (from Promise.all(…)) where the error is thrown
  3. the one that starts with Promise.resolve('ta-da!')

They don't wait for each other - you didn't tell them to do, and they won't do it magically themselves.
Instead, their flows are arbitrarily interleaved like it is the case for standard asynchronous functions as well (think of two setIntervals with different periods).

I was expecting the promises will be fulfulled immediately in syncronously

No. Promise callbacks are always (reliably) asynchronous, even when the promise is already settled.

Upvotes: 1

Walfrat
Walfrat

Reputation: 5353

I'll answer on a design point instead of blank testing like this :

The goal of promise is to make asynchronous requests, like server requests, in parallell.

So the order of when they're resolved will depends far more of the server answers than the javascript client loop on the broswer.

By design the flow of anyshcrounous requests are not made to be predictable. This is true for everything asynchrounous.

So if you need to make one request then another you need to wait to resolve the 1st promise before doing the other. If you need independant operations, say loading a dashboard with independant components you can fire all your asynchrounous requests in the same time. You won't get any problem from whatever the order they are resolved, in the case of the dashboard, do you really care that the 1st component is loaded before the 2nd one which show information that are totally independant ? Of course not.

Now if you just want to know about how it is implemented in a browser, i'd just say that it'll probably change if you change of broswer so it's totally not relevant. You have to make your javascript working for more than one browser aniway.

Upvotes: 1

Related Questions