0

I have three async functions but the third function is running before the second one resolves. What is wrong here?

 async function getSet () {
//get settings from asyncstorage and setstate
}

 async function pairs () {
//fetch data and set another state
}

 async function fetchIt () {
//fetch another data and set a third state
}
useEffect(() => {
    getSet()
      .then(pairs())
      .then(fetchIt())
      .then(() => {
        setLoading(false);
      });
  }, []);

fetchIt() is running before pairs()

markarth
  • 3
  • 2
  • I have corrected the code because I don't need their results. I want only to set the state. – markarth Aug 11 '21 at 01:14
  • i've corrected my question actually :) – markarth Aug 11 '21 at 01:20
  • [What is the difference between a function call and function reference?](https://stackoverflow.com/q/15886272) | [Confusion with how thenable callback works in Promise?](https://stackoverflow.com/q/59878462) – VLAZ Aug 11 '21 at 05:51
  • Does this answer your question? [What is the difference between a function call and function reference?](https://stackoverflow.com/questions/15886272/what-is-the-difference-between-a-function-call-and-function-reference) – Bravo Aug 13 '21 at 00:43

2 Answers2

1

The calls aren't chained properly. To make it simpler use async await:

  useEffect(() => {
    (async function () {
      await getSet();
      await pairs();
      await fetchIt();
      setLoading(false);
    })();
  }, []);

If each call depends on the result of the last it looks like

const r1 = await getSet();
const r2 = await pairs(r1);
// etcetera
see sharper
  • 11,505
  • 8
  • 46
  • 65
  • getting an error "An effect function must not return anything besides a function, which is used for clean-up" – markarth Aug 11 '21 at 01:22
  • To explain - React is checking what the useEffect function returns, as the returned value can be a clean up function. However an async function always returns a promise, so we need to wrap it in another function to stop the promise being returned. – see sharper Aug 11 '21 at 01:32
  • No @jfriend00 you can't. That's what I started with but had to modify it because I forgot that nicety of React. – see sharper Aug 11 '21 at 01:42
  • Please see comments above no. 2 and 4. – see sharper Aug 11 '21 at 01:43
  • OK, that's really inconvenient of React. Must have been designed before `async`. – jfriend00 Aug 11 '21 at 01:44
  • @Bravo a fair point - I might not have suggested it if I'd remembered this detail about React useEffect. – see sharper Aug 11 '21 at 01:44
  • @Bravo - The whole point of using `async/await` is that it's a LOT cleaner to sequence multiple asynchronous operations. In this case, you have to put in a AIIFE to get around React's objection to returning a promise, but IMO, that's worth it for cleaner sequencing of multiple asynchronous operations. Chaining a bunch of `.then()` is certainly doable, but not as clean IMO. – jfriend00 Aug 11 '21 at 01:45
  • It's clearly just a matter of preference. For consistency's sake I *always* use async await where I can. – see sharper Aug 11 '21 at 01:48
  • @Bravo I don't think async await is cool and new. I think it is simple to read and understand. And the fact that this question exists shows how easy it is to get the .then chaining wrong. But I have no interest in telling you when you *should* use it. Kindly do me the same favour. – see sharper Aug 11 '21 at 01:57
  • @Bravo I think you might have overreacted a little. Enjoy the sandpit. – see sharper Aug 11 '21 at 02:23
  • yeah, sure I did, that's why I deleted the comments. Because, apparently, expressing my opinion in response to an opinion is telling you what to do. yeah, I over reacted. – Bravo Aug 11 '21 at 02:28
  • FYI - you may want to correct yourself here https://stackoverflow.com/a/68675196/10549313 - wonder why that code doesn't have the same problem this code had before you fixed your error (I thought I'd seen you answer somewhere else recently) – Bravo Aug 11 '21 at 02:32
  • Thank you for the link. I remembered I made the same mistake recently but wasn't sure where. – see sharper Aug 11 '21 at 02:45
-3

You haven't chained the 'then's properly. They must return a promise as well. Read more here.

const getSet = async() => {
  //get settings from asyncstorage and setstate
  return new Promise((resolve, reject) => {
    resolve('getSet');
  });
}

const pairs = async() => {
  //fetch data and set another state
  return new Promise((resolve, reject) => {
    resolve('pairs');
  });
}

const fetchIt = async() => {
  //fetch another data and set a third state
  return new Promise((resolve, reject) => {
    resolve('fetchIt');
  });
}

getSet()
  .then(response => {
    console.log(response);
    return pairs();
  })
  .then(response => {
    console.log(response);
    return fetchIt();
  })
  .then(response => {
    console.log(response);
    // setLoading(false);
  });
  • while your code is technically correcter than the OP - your explanation is wrong - `.then` always return a Promise, and you don't need to return a promise inside a .then callback ... so thumbs up for correcter code (not the best, solution to be honest), but work on the explanation – Bravo Aug 11 '21 at 01:17
  • Ah right, thanks for pointing that out. Perhaps it can act as an example of how NOT to chain promises. ;) – sahilkhosla Aug 12 '21 at 19:54