ng.newbie
ng.newbie

Reputation: 3218

How does JavaScript know to wait for the result of an inner promise?

I am trying to wrap my head around the incredibly confusing topics of Promises in Javascript.

One of the doubts that I encountered is that what happens when a then() callback actually returns a promise.

Look at the code below taken from javascript.info

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

//Actually resolves before calling the next then()

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});

Anyone of the inner promises is actually fulfilled before moving on to the next then statement.

Why is that? How does Javascript know when the returned value is a promise itself?

Is there really a check within the JS interpreter for this? Like something like this-:

if(ret_value instanceof Promise) {
  wait_for_promise(ret_value);
}

This does not really make sense intuitively. You would think that the return value will be kept as is, ie the next then() in the chain would receive a promise and not the result of the promise.

I come from a Java background which is probably why this loose typing is irritating me.

Upvotes: 1

Views: 82

Answers (3)

hiddenAlpha
hiddenAlpha

Reputation: 400

In my opinion @kaiido s answer is the one You're searching for.

Simplified, an implementation of a promise internally could do a check like this one:

if( typeof(retValue.then)==="function" ) {
    retValue.then( yourCallback );
}else{
    yourCallback( retValue );
}

Wrote this on mobile phone. Please excuse my formatting.

Upvotes: 0

Kaiido
Kaiido

Reputation: 136638

The actual check that is performed is against thenables, not only against Promises.

If the returned value of a Promise resolver has a .then method, this method will be called, and the next resolver/rejecter will receive this method's value as argument:

const thenable = { // simple object, not an instance of Promise per se
  then: (res, rej) => setTimeout(() => res('from thenable'), 1000)
};
Promise.resolve(1)
  .then(v => thenable)
  .then(console.log)

Upvotes: 4

Adam Jenkins
Adam Jenkins

Reputation: 55613

Promise.resolve()
  .then(() => {
     return new Promise(res => setTimeout(() => res(1),1000))
   })
   .then(v => {
      console.log(v); //1
   });

Take a look at the second then in the example above: I passed in a callback to log the value. Because a Promise was returned in the first then, JavaScript will not execute the callback in the second then until the Promise returned from the first then is resolved.

If, instead, in the first then I passed back a value (below), instead of a Promise, JavaScript would execute the callback I passed into the second then immediately.

Promise.resolve()
  .then(() => {
     return 1
   })
   .then(v => {
      console.log(v); //1
   });

Why is that? How does Javascript know when the returned value is a promise itself?

Maybe this can illustrate an answer to your question:

let x = Promise.resolve();
console.log(x instanceof Promise); //true - JavaScript "knows" that x is a promise

let y = 1;
console.log(y instanceof Promise); //false

Upvotes: 1

Related Questions