Buzz
Buzz

Reputation: 1412

Different behaviour between 'returning a promise' and 'resolving with promise' inside a `new`-generated promise

It's not much I discovered Javascript Promise.
However I found out a behaviour I couldn't understand concerning the nesting of (new or returned) Promise inside Promises

That's the background (extPromiseX is a third-party function returning Promise):

Case 1:

function myAction(param) {
    return extPromise1(sql).then((result) => {
        [...]
        return extPromise2(sql2).then((result) => {
            [...]
            return extPromise3(sql3);
        })
   });
}

// Main Process
myAction(...)
.then(() => { 
    console.log('Process Terminated');
}).catch((error) => {
    console.error('Exit with error', error);
});

Now, as expected, I got from the console, in

1) extPromise1 completed
2) extPromise2 completed
3) extPromise3 completed
4) Process Terminated

Case 2:

function myAction(param) {
    return new Promise(function() {
        if (itsAllOkWithInputs) {
            // Some sync code here
            return extPromise1(sql).then((result) => {
                [...]
                return extPromise2(sql2).then((result) => {
                    [...]
                    return extPromise3(sql3);
                })
            })
        } else {
            throw 'Something went wrong';
        }
    });
}

// Main process
myAction(...)
.then(() => {
    console.log('Process Terminated');
}).catch((error) => {
    console.error('3) --> Exit with error', error);
})

In this second case extPromises are executed but the very first Promise remains pending (confirmed by debug). So the console shows:

1) extPromise1 completed
2) extPromise2 completed
3) extPromise3 completed

I empirically realized that I had to change myAction function as follow for the code to work:

function myAction(param) {
   return new Promise(function(resolve, reject) {
       if (itsAllOkWithInputs) {
           // Some sync code here
           let ep = extPromise1(sql).then(...);
           resolve(ep);
       } else {
           throw 'Something went wrong';
       }
   });
}

My question:
I thought returning a promise inside another parental one would make the parent resolving with the results of the child. This is the case inside the then code block applied to the external promises. Why this is not valid for the new Promise case?

Upvotes: 2

Views: 146

Answers (2)

Qwertiy
Qwertiy

Reputation: 21430

new Promise(function() {

You are not using neither resolve nor reject arguments (you actually even haven't declared them), so the promise will never get resolved or rejected. All other stuff is irrelevant.

If your function returns promise, you have to simply call it and return a result. If you don't know whether the function return promise or just a value, you can wrap it's call into Promise.resolve, but not in new Promise.

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138417

Because .then is meant to chain promises. You can return a Promise from inside the then callback, and then itself will return a new Promise.

The Promise constructor is supposed to construct a Promise from an underlying callback. If you return a Promise from inside a Promise constructor, you are doing something wrong conceptually. And that's why it does not work.

 function myAction(param) {
   if (itsAllOkWithInputs) {
       return extPromise1(sql).then(...);           
   } else {
       return Promise.reject('Something went wrong');
   }
 }

 // OR
async function myAction(param) {
   if (itsAllOkWithInputs) {
       await extPromise1(sql);     
   } else {
       throw 'Something went wrong';
   }
 }

Upvotes: 2

Related Questions