1
const b = () => {
  return new Promise(resolve => {
    resolve();
    Promise.resolve()
      .then(() => {
        console.log(1);
      })
      .then(() => console.log(3));
  });
};

const a = async () => {
  await b();
  console.log(2);
};

a();

Different behavior on safari , chrome(firefox), any standard described about this ?

Grant
  • 438
  • 2
  • 13
fallen leaf
  • 11
  • 1
  • 1
  • 3
    Can you describe what are the different behaviors? What result do you receive? – Giuliano Collacchioni Apr 15 '20 at 16:55
  • safari(13.1): 1 3 2 chrome(80.0), firefox(75.0): 1 2 3 macos catalina 10.15.4 – fallen leaf Apr 15 '20 at 16:59
  • That promise chain that logs `1` and `3` is totally independent from the rest of the code. Why would you even expect any specific ordering from that program? – Bergi Apr 15 '20 at 17:01
  • @Bergi What do you mean? i assume some *predictable* order should apply here – Sagiv b.g Apr 15 '20 at 17:10
  • just learning, help me thinking about react or event loop, etc. – fallen leaf Apr 15 '20 at 17:11
  • What behaviour is dfferent? If you're expecting promises to always behave the same you shouldn't. Promises will return, but it's not said when. So yes behaviour may change. – Trisma Apr 15 '20 at 17:14
  • Related: [JS Promise's inconsistent execution order between nodejs versions](https://stackoverflow.com/q/62032674/1048572) – Bergi Jul 28 '20 at 19:03

1 Answers1

1

You have two completely independent promise chains here:

Promise.resolve()
  .then(() => {
    console.log(1);
  })
  .then(() => console.log(3));


(async () => {
  await new Promise(resolve => {
    resolve();
  });
  console.log(2);
}());

There is no guaranteed ordering other that 3 happens after 1. The rest is affected by how promise callbacks are queued exactly, and there was a change in the spec of await (omitting one unnecessary thenable resolution procedure) that is probably not yet implemented in the Safari engine.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • +1 @Bergi, Do you have a reference to that change in spec? As for _"The rest is affected by how promise callbacks are queued exactly"_, i think there is a predictable order, each "branch" will queued first and only after that the next chained thenable. (at least AFAIK). This should yield `1 2 3 4` on all browsers `Promise.resolve().then(() => console.log(1)).then(() => console.log(3)); Promise.resolve().then(() => console.log(2)).then(() => console.log(4));` – Sagiv b.g Apr 15 '20 at 18:46
  • 1
    @Sagivb.g See https://v8.dev/blog/fast-async for all the gory details that in my opinion nobody should be concerned with (and that shouldn't have required a spec change if the queuing wouldn't have been standardised in that much detail). Yes, the order is kinda predictable and (in theory) consistent between engines, but as soon as you replace the implicit `return undefined` in one of these callbacks with `return Promise.resolve(undefined)`, the order might change. – Bergi Apr 15 '20 at 18:58
  • Thanks! As for the _"but as soon as you replace the implicit return undefined in one of these callbacks with return Promise.resolve(undefined), the order might change"_, I know it will change that order but TBH i'm not sure i know why, AFAIK any returned value is implicitly wrapped with a `Promise.resolve`, so i don't know what's the subtle difference here. My mental model is that each first `.then` creates a "branch" and all branches are executed first and only then the chained `.then`'s by order. unless one of them returns a promise (which creates a new branch on the next loop?) – Sagiv b.g Apr 15 '20 at 19:58