简体   繁体   中英

How to return an extended promise instance from an async function?

I'm just toying around with some ideas for my framework, lets say I extended the promise class like this

class cool_promise extends Promise {
    cool_function() {
        console.log("I am cool");
    }
}

and had an async function like

async cool_function() {
    return "functioning";
}

now by default cool_function just returns a regular Promise when executed synchronously but is it possible to make the async functions specific to my framework return my extended promise class instead?

The async keyword will always cause a function to return a native Promise. To return a custom promise your function needs to be declared without async and return the Promise directly.

You could write your async functions like normal but wrap them with a function that returns a CoolPromise instead before exposing them as part of your framework's interface:

 class CoolPromise extends Promise { coolFunction ( ) { return 'I am cool'; } static decorate ( func ) { return function (...args) { return CoolPromise.resolve( func.call( this, ...args ) ); }; } } // Some module with an async function in it const module = function Module ( ) { async function foo( ) { return 'bar'; } // Decorate functions before exposing them from your modules return { foo: CoolPromise.decorate( foo ) }; }( ); // Verify that module.foo( ) returns a CoolPromise (async ( ) => { console.log( await module.foo( ) ); console.log( module.foo( ).coolFunction( ) ); })();

No, you would have to convert it manually with cool_promise.resolve(cool_function()) . Without using a JavaScript preprocessor, async functions will always return a native Promise .

An alternative sometimes is to extend the native Promise prototype:

Object.defineProperty(Promise.prototype, 'cool_function', {
    configurable: true,
    writable: true,
    value() {
        console.log("I am cool");
    },
});

Modifying globals always risks conflicting with other libraries/user code or later changes to the language, though. Sometimes it's better to just have a standalone function. Maybe it'll be possible to use that kind of function in a pipeline similar to the method call syntax someday – for example, there's a proposal that would let you do this or something like it:

const cool_extension = (promise) => {
    console.log("I am cool");
};

cool_function() |> cool_extension
// cool_function().cool_extension(), when extending prototype

And in the meantime, cool_extension(cool_function()) is not too bad and comfortably familiar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM