1

I have some javascript code that I'm trying to understand. I have a function that returns a Promise, and within one of the then blocks I have an axios.post (from axios library). When this function runs, in the console I see "finish here", but I never see "post complete". I assume that's because the function finishes before the axios.post response returns? Is that correct? What would I need to do if I also wanted "post complete" to show in the console?

function X () {
  return new Promise((resolve, reject) => {
    if (x) {
      ...
      resolve();
    } else {
      ...
      reject();
    }
  }).then(() => {
    axios.post(
      url, 
      data
    ).then((response) => {
      ...
      console.log("post complete");
    });
  }).then(() => {
    ...
    console.log("finish here");
  });
}
user1647525
  • 311
  • 3
  • 14

1 Answers1

2

You're not returning the axios promise up to the main promise chain. You really shouldn't nest promises like that anyway; if a then or catch callback returns a promise, it'll bubble up to the main chain and can be chained directly from there. Try this instead:

function X () {
  return new Promise((resolve, reject) => {
    if (x) {
      ///...
      resolve();
    } else {
      ///...
      reject();
    }
  })
  .then(() => axios.post(url, data))
  .then(response => {
    //...
    console.log("post complete");
  })
  .then(() => {
    ///...
    console.log("finish here");
  });
}
IceMetalPunk
  • 5,476
  • 3
  • 19
  • 26
  • 2
    The callback for the axios post returns that promise. OP's did not, since arrow functions with curly braces don't implicitly return anything, and they didn't explicitly use `return` either. I'm also chaining the `.then` for the post directly in the main promise chain rather than nesting it, so it's easier to read. – IceMetalPunk Sep 16 '19 at 19:25
  • 1
    FYI, nesting the `.then()` callback _is_ valid practice in a scenario where the continuation needs access to local variables declared in the previous continuation (e.g. `url` and `data` in this case, if they were declared in the body of the first `.then()` callback) – Patrick Roberts Sep 16 '19 at 19:28
  • @PatrickRoberts I would say in that case, if there's no way to refactor those variables out to a higher scope, a better solution would be to pass them along to the next callback with `Promise.all`. Nesting chains like this makes it harder to follow, as the OP has discovered :) (Or, you know, maybe it's best just to skip all this and jump straight to async/await :D ) – IceMetalPunk Sep 16 '19 at 19:34
  • @IceMetalPunk Explicitly passing variables along to the next continuation or capturing them within a closure is a matter of style preference. Both are valid solutions, and the fact that either is a viable approach doesn't disqualify the other. But yes, `async` / `await` is syntactic sugar for chaining promises and implicitly capturing variables with closures (i.e. nesting continuations). – Patrick Roberts Sep 16 '19 at 19:40
  • I'm not saying it's "disqualified" -- it works just fine, obviously. It's just harder to read as it leads to a pyramid of callbacks. Being harder to read makes it easier for bugs to sneak in -- like this question showed, as one did :) Everything that works equivalently is a matter of preference, but some things are harder to read than others. – IceMetalPunk Sep 16 '19 at 19:46
  • I would personally argue that explicitly passing additional values along to the next continuation with the promise being awaited is less readable, and more prone to bugs, since doing so requires more cognitive load following the continuation chain (i.e. destructuring an array of elements or an object of properties rather than a single resolved value from the `.then()` callback parameter), but I acknowledge that's my opinion talking, which is why I initially stated "it's a matter of style preference". – Patrick Roberts Sep 16 '19 at 19:51
  • But you don't have a single resolved value in either case; you have two, just one is nested inside the callback that has the other. See? It's already harder to follow when you nest :P – IceMetalPunk Sep 16 '19 at 20:03
  • @PatrickRoberts It's [totally valid](https://stackoverflow.com/a/28250687/1048572) (though [unnecessary](https://stackoverflow.com/a/22000931/1048572) here), but doesn't change that you need to `return` the inner promise chain from the outer `then` callback – Bergi Sep 16 '19 at 20:08
  • @Bergi I never contested that. – Patrick Roberts Sep 16 '19 at 20:09