Home > Net >  Promises being executed when they shouldn't be
Promises being executed when they shouldn't be

Time:12-17

I have several db mutations that I would like to execute all at once, instead of synchronously. The problem that I'm running into, is that when I try to push these promises into an array, they execute.

What am I doing wrong here? I've also tried pushing anonymous functions, like this,

promises.push(
    async () => await someDbMutation1({ someForeignKey: "10" }),
)

but they aren't execute during Promise.all.

confident-austin-sifop

import * as React from "react";
import "./styles.css";

const someDbMutation1 = async ({ someForeignKey }) => {
  return await new Promise((resolve) => {
    console.log("should not enter");
    return setTimeout(() => {
      resolve("aa");
    }, 2000);
  });
};

const someDbMutation2 = async ({ someParameter }) =>
  await new Promise((resolve) =>
    setTimeout(() => {
      resolve();
    }, 2000)
  );

export default function App() {
  const [loaded, setLoaded] = React.useState(false);

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

  const init = React.useCallback(async () => {
    const promises = [
      someDbMutation1({ someForeignKey: "10" }),
      someDbMutation2({ someParameter: "abc" })
    ];

    // await Promise.all(promises);

    setLoaded(true);
  }, []);

  return <div className="App">{loaded && <div>done</div>}</div>;
}

I would expect these promises in the promises array to be executed during a call to Promise.all, but clearly that's not the case here. I've noticed this only recently, when I passed null as a value to a foreign key, at which point the key constraint in my db picked it up and threw an error.

Now I'm worried, because I frequently use a promises array and loop over db objects and push mutation queries into promises -- this means, that each request is executed twice! I'm not sure what I'm missing here.

CodePudding user response:

For the first part of your question where you say that it's not executing:

promises.push(
    async () => await someDbMutation1({ someForeignKey: "10" }),
)

it's because you are pushing an anonymous function not a promise - They are two different things. Based on your array name, I think expected behavior would be for you to do this instead:

promises.push(
    someDbMutation1({ someForeignKey: "10" })
)

If you want all promises to be executed at a single point in time then you could do this instead:

queries.push(
    async () => await someDbMutation1({ someForeignKey: "10" }),
)

/ ** -- some point later -- ** /

const promises = queries.map(q => q()) // Execute queries
const results = await Promise.all(promises) // Wait for queries to finish

In addition, you have a misunderstanding on how Promise.all works here:

I would expect these promises in the promises array to be executed during a call to Promise.all

Promise.all doesn't execute the promises, it waits for the promises to resolve. There is a reference here.

So in this part:

const promises = [
  someDbMutation1({ someForeignKey: "10" }),
  someDbMutation2({ someParameter: "abc" })
];

You are actually executing the functions so that if you were to console.log the promises array it would look something like this:

[
  Promise (unresolved),
  Promise (unresolved)
];

And then after await Promise.all(), the promises array would look like this:

[
  Promise (resolved: value),
  Promise (resolved: value)
];

CodePudding user response:

Issue 1: Promises must be awaited in the block that actually awaits for them.

const someDbMutation1 = async ({ someForeignKey }) => {
  return new Promise((resolve) => {
    console.log("should not enter");
    return setTimeout(() => {
      resolve("aa");
    }, 2000);
  });
};

const someDbMutation2 = async ({ someParameter }) =>
  await new Promise((resolve) =>
    setTimeout(() => {
      resolve();
    }, 2000)
  );

The problem is you are executing the promises. You should instead add them into an array as anonymous functions that call your function with the parameters you want. So this should look like this. :

const init = React.useCallback(async () => {
    const promises = [
      async () => someDbMutation1({ someForeignKey: "10" }),
      async () => someDbMutation2({ someParameter: "abc" })
    ];

    await Promise.all(promises);

    setLoaded(true);
  }, []);

I hope this is the answer you are looking for.

  • Related