# Zero-overhead Async/Await [Callbacks are significantly faster](https://hackernoon.com/nodejs-48x-faster-if-you-go-back-to-callbacks) than `Promise`s 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: ```ts type Callback<V, E = unknown> = | (error: E) => void; | (error: void, value: V) => void; ``` 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: ```js await cb fs.readFile('myfile.txt', 'utf-8', cb); ``` Likewise, the async function syntax would also be extended to allow *AsyncCallbackFunction* type. There as well, the syntax would allow a single callback identifier: ```js async cb function(args, cb) { // ... } ``` 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: ```js async _ function getFileData(filename, _) { try { const data = await _ fs.readFile('myfile.txt', 'utf-8', _); return 'mydata: ' + data; } catch (error) { if (!!error && typeof error === 'object' && error.code === 'ENOENT') { throw new Error('not found'); } throw error; } } ``` The code would be equivalent to the existing JavaScript: ```js function getFileData(filename, callback) { const onCatch = (error) => { if (!!error && typeof error === 'object' && error.code === 'ENOENT') { callback(new Error('not found')); } else { callback(error); } }; try { fs.readFile('myfile.txt', 'utf-8', (err, data) => { if (err) { onCatch(err); } else { try { callback(null, 'mydata: ' + data); } catch (error) { onCatch(error); } } }); } catch (error) { onCatch(error); } } ``` 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. ```js async function getFileDataAsync(filename) { try { const data = await promisify(fs.readFile)('myfile.txt', 'utf-8'); return 'mydata: ' + data; } catch (error) { if (!!error && typeof error === 'object' && error.code === 'ENOENT') { throw new Error('not found'); } throw error; } } ``` Or, equivalently, the good old `promisify` utility could convert our callback powered function to this `Promise` powered one: ```js const getFileDataAsync = promisify(getFileData); ``` ## Sugar Syntax When awaiting one can explicitly specify the callback identifier and explicitly use it as an argument: ```js await myCallback fs.readFile('a.txt', myCallback) ``` If the await identifier `myCallback` is not used, it is automatically inserted in the function call as the last argument: ```js await _ fs.readFile('a.txt') ``` When defining an async callback function, the above text proposed to explicitly specify the callback identifier, like so: ```js async myCallback function getData(filename, myCallback) {} ``` Instead it can be reduced by simply using the `async` keyword once, in place of some argument: ```js function getData(filename, async) {} ``` The above syntax modifications reduce the example `getFileData` function to the following: ```js function getFileData(filename, async) { try { const data = await _ fs.readFile('myfile.txt', 'utf-8'); return 'mydata: ' + data; } catch (error) { // ... } } ``` ## Using with TypeScript From the point of view of TypeScript, to define a new async callback function, one can simply use the `CallbackType`: ```ts type GetFileData = (filename: string, callback: Callback<string>) => void; ``` Alternatively, the `async` type shorthand could be introduced, to make it more explicit: ```ts type GetFileData = (filename: string, async<string>) => void; ``` Maybe it could be called `callback`: ```ts type GetFileData = (filename: string, callback<string>) => void; ```