Sahuagin Sahuagin - 23 days ago 6
TypeScript Question

"Inject" callback with async/await

I'm refactoring some promise code to using

async
/
await
, and it works great except for one thing.

Something that a
Promise
lets you do is sort of "inject" the callback wherever you'd like. Ex:

public DoSomethingAsync() {
return new Promise<void>(done => {
// do some stuff
done();
});
}


Or even maybe the callback is wrapped up in another callback:

public DoSomethingAsync() {
return new Promise<void>(done => {
const somethingDeferred = GetSomethingDeferred();
somethingDeferred.onsuccess = () => {
// some success code
done();
};
});
}


There is a similar problem with the "reject" handler.

Is there a way to refactor these to
async
/
await
? Or are they stuck wrapped up in a
new Promise...
block?

I think it's possible that the first example can be reduced all the way to simply:

public async DoSomethingAsync() {
// do some stuff
}


Because the callback will automatically be called afterwards anyway. But the second example seems much more problematic.

Answer

Is there a way to refactor these to async/await?

No.

Or are they stuck wrapped up in a new Promise... block?

Yes. You need to promisify these functions that are asynchronous but don't return a promise already using the new Promise constructor (or a helper function that can shorten the repetitive code), there is no way around that. You'd rewrite your second example to

public async DoSomethingAsync() {
    await new Promise<void>((resolve, reject) => {
        const somethingDeferred = GetSomethingDeferred();
        somethingDeferred.onsuccess = resolve;
        somethingDeferred.onerror = reject;
    });
    // some success code
    return …;
}

or, with a helper function:

function toPromise(somethingDeferred) {
    return new Promise<void>((resolve, reject) => {
        somethingDeferred.onsuccess = resolve;
        somethingDeferred.onerror = reject;
    });
}

public async DoSomethingAsync() {
    await toPromise(GetSomethingDeferred());
    // some success code
    return …;
}