user6665922
user6665922

Reputation:

Returning a Promise inside of a "then" handler causes another unrelated Promise to be resolved with the returned Promise's resolution value

I've been trying to figure this one out and I'm wondering how the resolution value gets passed too getAnswer's then call. First I return the result of add which I think returns a Promise which allows me to use a then call on the then method on getAnswer, but then how does the second return statement get passed to it?

 function add(num1, num2) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {resolve(num1 + num2);}, 500)

  });
}

function getAnswer() {
  return add(5, 5).then((res) => {
    console.log(res);
    return new Promise((resolve, reject) => {
      resolve("How does this get passed too getAnswer's then function?");
    });
  });
}

getAnswer().then((res) => {
  console.log(res);
})

Upvotes: 0

Views: 103

Answers (1)

doubleOrt
doubleOrt

Reputation: 2507

The Basics:

add returns a Promise -- which is an instance of the Promise object, every instance of Promise has a then method which you can use to observe that promise's resolution.
For chaining purposes, then has been designed in such a way that it returns a Promise itself (so, every then call in JavaScript will always return a new promise). The promise returned by then will be resolved with the return value of its handlers (more on this later).

Now, when you say:

  return add(5, 5).then((res) => {
    console.log(res);
    return new Promise((resolve, reject) => {
      resolve("How does this get passed too getAnswer's then function?");
    });
  });

You are not returning add's result, you are returning the promise that you created by calling then on add's result (this is just standard JS behavior).

Your Question:

but then how does the second return statement get passed to it?

Here is what the then method returns, according to MDN (the parts inside ([]) are my additions):

A Promise in the pending status ([this is what your first return statement is actually returning]). The handler function (onFulfilled or onRejected) gets then called asynchronously ([the handler in your example is the function you've passed to the then inside getAnswer]). After the invocation of the handler function, if the handler function:

  • returns a value, the promise returned by then gets resolved with the returned value as its value;
  • throws an error, the promise returned by then gets rejected with the thrown error as its value;
  • ([this is your case -- your second return]) returns an already resolved promise, the promise returned by then gets resolved with that promise's value as its value;
  • returns an already rejected promise, the promise returned by then gets rejected with that promise's value as its value.
  • returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. Also, the value of the promise returned by then will be the same as the value of the promise returned by the handler.

Personally, whenever I see a Promise being returned by then's handlers, I just assume -- to simplify the situation for my mind -- that the Promise returned by then originally has been replaced with the Promise that was just returned by one of then's handlers. Of course, this mental mapping is parallel to the actual functionality, AFAIK.

So, to sum it up:

  1. getAnswer returns a promise -- created by add(5, 5).then(...).
  2. you then observe that returned promise using then (getAnswer().then(...)) -- unrelated here, but this call also creates a promise.
  3. it happens that the handler for the observation of the promise returned by the add call (this handler is the function you pass to then in #1) returns a promise as well, and the rules are that if a handler of then returns a promise p, then whenever p is resolved with a value v, the original promise -- created by then -- will be resolved with v as well.
  4. Finally, the handler you passed to the then in #2 to observe the promise returned by getAnswer() will be called with the value v from #3.


Feel free to ask for any clarifications, but before doing so, read this article thoroughly.

Upvotes: 1

Related Questions