Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between returning a promise vs returning undefined inside a promise

I am not really sure I understand the difference between these two common scenarios.

Say we have this:

user.save().then(function(val){
   anotherPromise1(val);
}).then(function(val){
   anotherPromise2(val);
}).catch(function(err){

});

versus:

user.save().then(function(val){
   return anotherPromise1(val);
}).then(function(val){
   return anotherPromise2(val);
}).catch(function(err){

});

I know it makes a difference but how exactly?

like image 625
Alexander Mills Avatar asked Feb 16 '16 08:02

Alexander Mills


People also ask

What does returning a Promise do?

Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.

Does Promise then return a Promise?

Promise.prototype.then() The then() method returns a Promise . It takes up to two arguments: callback functions for the success and failure cases of the Promise .

Which method returns a Promise?

resolve() method in JS returns a Promise object that is resolved with a given value. Any of the three things can happened: If the value is a promise then promise is returned.

How do you return a value from a Promise?

It is the fetch() function that returns a value, which is a Promise instance. It is the Promise instance on which you call the then() method, passing in a callback function, which will be eventually be fired when the async code finishes (and internally, calls resolve() ).


1 Answers

If you don't return a value from the then callback, you're effectively returning undefined. The next then callback will run immediately, and see undefined as the resolution value.

If you return a promise from the then callback, the second then callback waits on that promise (indirectly, but that doesn't really matter), and when that promise is resolved, gets the resolution value from that promise.

(This is covered by the then specification in the Promises/A+ spec, but slightly by omission — it doesn't explicitly mention what should happen if onFulfilled doesn't return anything, but in JavaScript, calling a function always gives you a resulting value; if the function doesn't explicitly return something, undefined is the result of calling it. JavaScript doesn't have the concept of void methods a'la C/C#/C++/Java.)

You can see it in this script live copy on Babel's REPL:

let start = Date.now();
function elapsed() {
  let rv = String(Date.now() - start);
  while (rv.length < 4) {
    rv = "0" + rv;
  }
  return rv;
}
function anotherPromise(type, val) {
  console.log(`${elapsed()}: anotherPromise[${type}] got ${val}`);
  return new Promise(resolve => {
    setTimeout(() => { resolve(val * 2); }, 1000);
  });
}
function anotherPromise2(type, val) {
  console.log(`${elapsed()}: anotherPromise2[${type}] got ${val}`);
  return new Promise(resolve => {
    setTimeout(() => { resolve(val * 3); }, 10);
  });
}
let user = {
  save: () => {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(42);
      }, 10);
    });
  }
}

// Without return
user.save().then(function(val){
   anotherPromise("without", val);
}).then(function(val){
   anotherPromise2("without", val);
}).then(function() {
  console.log(`${elapsed()}: All done`);
}).catch(function(err){
});

user.save().then(function(val){
   return anotherPromise("with", val);
}).then(function(val){
   return anotherPromise2("with", val);
}).then(function() {
  console.log(`${elapsed()}: All done`);
}).catch(function(err){
});

The output is (for example):

0015: anotherPromise[without] got 42
0017: anotherPromise2[without] got undefined
0018: All done
0020: anotherPromise[with] got 42
1021: anotherPromise2[with] got 84
1032: All done

Note the differences between without a return and with a return:

  • Without, anotherPromise2 was called immediately (as we can see from the elapsed time values) and received undefined.

  • With, anotherPromise2 waited for anotherPromise's resolution to occur, and then received 84 (anotherPromise's resolution value)

like image 100
T.J. Crowder Avatar answered Nov 14 '22 22:11

T.J. Crowder