Home > Back-end >  Log message printed for promises during a `push` to an array but not a call to `Promise.all`
Log message printed for promises during a `push` to an array but not a call to `Promise.all`

Time:01-24

I'm trying to understand something about the following behavior for promises.

When I push a promise to the promises array, the console.log is executed. I think this is because as I push, I actually execute the promises.

But then when I try doing Promise.all, I don't see the same console.log messages being printed, it's just silence. I can see the return values of each resolve if I destructure them from the Promise.all and console.log them, but, again, I don't see the console.log messages (such as Printed for promise A during push).

Why is this happening?

import * as React from "react";

const promiseA = async ({}) => {
  return await new Promise((resolve) => {
    console.log("Printed for promise A during push");

    resolve("promise a resolved");
  });
};

const promiseB = async ({}) => {
  return await new Promise((resolve) => {
    console.log("Printed for promise B during push");

    resolve("promise b resolved");
  });
};

const Component = React.memo(() => {
  React.useEffect(() => {
    init();
  }, []);

  const init = React.useCallback(async () => {
    let promises = [];
    promises.push(promiseA({})); // 'Printed for promise A during push'
    promises.push(promiseB({})); // 'Printed for promise B during push'

    await Promise.all(promises); // silence, nothing is printed

    /*
        // And if I do the following, I see the strings in `resolve`:
        const [responseA, responseB] = await Promise.all(promises);
    
        console.log("responseA", responseA); // responseA promise a resolved
        console.log("responseB", responseB); // responseB promise a resolved
    */
  }, []);

  return <div />;
});

export default Component;

CodePudding user response:

Some of the confusion here is your naming.

promiseA and promiseB aren't promises in your code, they are functions that returns a Promise.

You call the functions promiseA and promiseB, and you add the return values to the array.

Using the return value of a function will not call the function again. The promise objects returned can be used to wait for the code in the functions to complete. In this case, they aren't asynchronous so they will be immediately resolved/complete.

Promise.all returns a new promise that is resolved when all the promises in the array are resolved. In this case, that is again immediately.

But, don't confuse the function called promise with the return value which is actually a Promise

CodePudding user response:

Promises can't be "executed". Promises don't describe actions, they describe the results of some actions.

The function you pass to the Promise constructor is called immediately when the constructor is called. Its job is to initiate the actions, the result of which the promise represents. That means that the actions are initiated when the promise is created.

new Promise((resolve) => {
  console.log("Printed during promise creation");

  resolve("resolved");
});

...is the same as writing...

console.log("Printed at the same time, but from outside the Promise callback");

new Promise((resolve) => {
  resolve("resolved");
});

So in your code, it's not push creating those promises. It's you calling those promise-creating functions.

promises.push( promiseA({}) );
//                     ^^^^--- calling function `promiseA`

The thing that you made your functions async can be another level of confusion. Let's rewrite your code in a bit clearer way:

//This used to be named `promiseA`
const createPromiseA = () => {
  console.log("Called createPromiseA, about to create promiseA")
  return new Promise((resolve) => {
    console.log("Promise A created");

    resolve("Promise A resolved");
  });
};

//This used to be named `promiseB`
const createPromiseB = () => {
  console.log("Called createPromiseB, about to create promiseB")
  return new Promise((resolve) => {
    console.log("Promise B created");

    resolve("Promise B resolved");
  });
};

let promises = [];

let promiseA = createPromiseA(); //Called createPromiseA, about to create promiseA | Created promiseA
let promiseB = createPromiseB(); //Called createPromiseB, about to create promiseB | Created promiseB

//All the following will just move those promises around, no logs.
promises.push(promiseA);
promises.push(promiseB);

//Neither will this log
let results = await Promise.all(promises); 

//Logs the results as expected
console.log(results) //["Promise A resolved", "Promise B resolved"]
  •  Tags:  
  • Related