Symbol.await proposal

James M Snell jasnell at gmail.com
Mon Jun 22 19:21:39 UTC 2020


For many legacy code bases that are based on callbacks mechanisms like
node.js' promisify function are required to help facilitate the transition
from callback centric code to Promise-centric. A lot of the time, these can
follow straightforward rules without requiring customization. However, at
other times it is necessary for user code to provide custom implementations
of the Promise-version of the function.

In Node.js, we accomplish this by allowing a function to have a symbol
attached whose value is an alternative function that is returned by the
promisify function

For instance,

  function myFunction(foo, bar, callback) {
    callback(null, foo, bar);
  }
  myFunction[util.customPromisifySymbol] = async function(foo, bar) {
    return [foo, bar];
  }

  const { promisify } = require('util');
  const mine = promisify(myFunction);
  (async () => console.log(await mine('a','b')))();

As a convenience built into the language, it would be nice to be able to
short-circuit the need to call promisify with a special language-level
Symbol used specifically for this purpose:

  function myFunction(foo, bar, callback) {
    callback(null, foo, bar);
  }
  myFunction[Symbol.await] = async function(foo, bar) {
    return [foo, bar];
  }

  (async () => console.log(await myFunction('a','b')))();

The idea here is that if the function being awaited has the [Symbol.await]
property whose value is a function, then that function is called when the
await keyword is used. That is,

  myFunction('a', 'b', callback); // Invokes myFunction directly
  await myFunction('a', 'b');  // Invokes myFunction[Symbol.await]

if the Symbol.await property is not set or is not callable, then it would
fallback to default behavior.

Automatic handling of this binding should also happen but has some
technical detail to work out:

  const obj = {
    a: 1,
    foo() {}
  };
  obj.foo[Symbol.await] = async function() {
    return this.a;
  }
  await obj.foo();  // Calls await obj.foo[Symbol.await] with bound this

This approach would make it far easier for legacy code bases to make the
transition to async/await syntax while maintaining legacy compat.

Before writing up a formal proposal, I wanted to solicit some feedback on
this approach to see what folks thought.

- James
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20200622/db87b061/attachment.html>


More information about the es-discuss mailing list