Search code examples
javascripttypescriptes6-promise

Promise.resolve - Unexpected result


I don't understand Promises. I know that Promises are Objects that can finish successfully or erroneously. And promises are good to execute asynchronous functions and concatenate other asynchronous function via then. The result of a promise is passed as parameter to a callback function inside the then method of the last executed promise (if the promise ends right).

This example doesn't work. I am simulating an asynchronous call via setTimeout. My function returns an integer. I am expecting to get a 5 as result of prom2. Why doesn't work? What I am doing wrong and why?

var getProductId = function(){
    setTimeout(function () {
        return 5;
    }, 1500);
};
var prom2 = Promise.resolve(getProductId);

prom2.then(function(result){
    console.log("5 = " + result);
});

I tried also:

var getProductId = function(){
    setTimeout(function () {
        return 5;
    }, 1500);
};
var prom2 = Promise.resolve(getProductId());

prom2.then(function(result){
    console.log("5 = " + result);
});

Note: I want to use Promise.resolve and not new Promise.


Solution

  • All that Promise.resolve does is it takes an expression and turns it into a Promise that immediately resolves to that expression. If the expression is any type of plain value (primitive, array, object, etc) other than a Promise, then Promise returned by Promise.resolve will still resolve immediately. Your getProductId function is not returning anything, so your prom2 results in a Promise that resolves immediately to the value of undefined.

    Promise.resolve will not help your situation - you need to convert a callback to a Promise, and the only way to do that is to use the new Promise constructor:

    console.log('start');
    const getProductId = () => new Promise(res => setTimeout(res, 1500, 5));
    getProductId().then(res => console.log(res));

    The time to use Promise.resolve is if you already have a value (synchronously) and want to turn it into a Promise that you can call .then on. For example, by using Promise.resolve('begin') as the initial value for the accumulator in the following code, a simple Promise chain can be constructed with reduce:

    const prom = ['foo', 'bar', 'baz']
      .reduce((lastProm, str) => (
        lastProm.then((lastStr) => {
          console.log(lastStr);
          return str;
        })),
        Promise.resolve('begin')
      );
      
    prom.then((lastStr) => {
      console.log(lastStr);
      console.log('end');
    });