Ayush Gupta
Ayush Gupta

Reputation: 9285

How to return a Promise as the result of another promise when it is resolved

Here a sample code:

function getExtendedPromise() {
    const promise = new Promise((resolve) => {
        setTimeout(() => {
            resolve('Hi');
        }, 1000)
    });
    promise.on = () => {
        console.log('on listener called')
    };
    console.log('getExtendedPromise: ', promise);
    return promise;
}

async function callExtendedPromise() {
    await Promise.resolve();
    return Promise.resolve(getExtendedPromise())
}

const promise = callExtendedPromise();
console.log('callExtendedPromise Try: ', promise);
callExtendedPromise().then((result) => {
    console.log('Final Result: ', result)
});

Log Results:

callExtendedPromise Try:  Promise { <pending> }
getExtendedPromise:  Promise { <pending>, on: [Function] }
getExtendedPromise:  Promise { <pending>, on: [Function] }
Final Result:  Hi

As seen from the sample above, when the object is logged inside the getExtendedPromise() function, it has an on property. I then wrap it in a Promise.resolve, and return it to the caller because I want the caller to get the Promise object with the on property.

However, when calling callExtendedPromise(), I am not able to access that wrapped promise with the on property.

How can I get that promise instance with the on property?

getExtendedPromise() is the part of a library and not open for modification.

P.S. the choice of the structure of the extended promise is not my choice in the original code, but rather the structure returned from a library.

Upvotes: 2

Views: 219

Answers (1)

Daniel Thompson
Daniel Thompson

Reputation: 536

Unfortunately, it may not be possible to return an extended Promise from an async function. (Following taken from async function on MDN)

...the return value of an async function is implicitly wrapped in Promise.resolve.


If you can modify callExtendedPromise and can confine consuming the extended parts (i.e. any call to on) to that method, then I'd do that. Alternatively, you could use some sort of returned object (see below). I'd recommend against this in general (though the real root of the issue is trying to extend the individual Promise instance and then also use it as a Promise, which it sounds like you have no way to adjust), but it should be

async function callExtendedPromise() {
    await Promise.resolve();
    return {extendedPromise: getExtendedPromise()};
}

...

const extendedPromise = (await callExtendedPromise()).extendedPromise;
extendedPromise.on(); // 'on listener called'
extendedPromise.then(message => console.log(message)); // 'Hi!'

Upvotes: 3

Related Questions