Search code examples
javascriptes6-promise

Promise.resolve vs Promise.resolve().then()


A question asked here before, with the exact same title as this one, was answered with a "You should not use that, use this instead", I am looking to know what it does, not what else could I do, it's about understanding not a simple copy a paste.

My question is quite simple, what is the difference between these three approaches when creating a promise?

const API = (item, fail) =>
  new Promise((resolve, reject) => {
    if (fail) reject(item + ' ...with an error');
    setTimeout(() => resolve(item), 1000);
  });

(async () => {
  const pro1 = Promise.resolve(API('I am inside resolve'));
  const pro2 = Promise.resolve(API('I am inside resolve', true));

  const pro3 = Promise.resolve().then(() => API('I am thenable'));
  const pro4 = Promise.resolve().then(() => API('I am thenable', true));

  const pro5 = new Promise((resolve) => resolve(API('I am a new promise')));
  const pro6 = new Promise((resolve) => resolve(API('I am a new promise', true)));

  const store = [pro1, pro2, pro3, pro4, pro5, pro6];

  const results = await Promise.allSettled(store);

  for (const { status, value, reason } of results) {
    if (status === 'fulfilled') console.log(value)
    else console.log(reason)
  }
})();


Solution

  • The difference is in job to be done. While all of this methods are valid, they have different cost and predictability.

    1. Promise.resolve() produces single resolved Promise instance, and depending on value provided to the call JS engine have information to optimize it. It makes all work to be done in a single call to underlying code of the JS engine (usually C++, but could be Java or WASM). So it's always the best choice.
    2. Promise.resolve().then(() => API(/*...*/)) Produce several Promise instances: one at Promise.resolve() and other at .then() call. It also allocates more memory and make several (3 or more) redundant jumps between JS and the engine. It's hardly optimizable and requires intensive heuristics to be performed to figure out is this call optimizable. It's the worst option.
    3. new Promise((resolve) => resolve(API(/* ... */)) allocates one function and one Promise instance and makes two jumps between JS and the engine. It's harder to optimize this call, due to nature of JS.