Vadim Dalecky1 year ago

Zero-overhead Async/Await

Callbacks are significantly faster than Promises in Node.js. How can we get the performance of callbacks while benefiting from the Promise and async/await syntax?

JavaScript could introduce CallbackAwaitExpression, which syntactically would look very much like the existing AwaitExpression but it would operate on top of callbacks instead of promises.

The callbacks would have the following form:

The new CallbackAwaitExpression would have an extra identifier parameter of type Callback, syntactically in between the await keyword and the expression being awaited, for example, note the cb identifier:

Likewise, the async function syntax would also be extended to allow AsyncCallbackFunction type. There as well, the syntax would allow a single callback identifier:

Putting this all together, this would allow to write async/await syntax-powered code, while benefiting from the performance of callbacks. It would allow to write code like this:

The code would be equivalent to the existing JavaScript:

Here is how the above code can look like using the existing async/await syntax. The code is almost equivalent to the async/await callback proposal, but less performant due to Promise usage.

Or, equivalently, the good old promisify utility could convert our callback powered function to this Promise powered one:

Sugar Syntax

When awaiting one can explicitly specify the callback identifier and explicitly use it as an argument:

If the await identifier myCallback is not used, it is automatically inserted in the function call as the last argument:

When defining an async callback function, the above text proposed to explicitly specify the callback identifier, like so:

Instead it can be reduced by simply using the async keyword once, in place of some argument:

The above syntax modifications reduce the example getFileData function to the following:

Using with TypeScript

From the point of view of TypeScript, to define a new async callback function, one can simply use the CallbackType:

Alternatively, the async type shorthand could be introduced, to make it more explicit:

Maybe it could be called callback: