Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use 'await' in parameter default in an async function

I want to use an async function as a default parameter but I get an error: 'await' is not a valid idientifier name in an async function. Is this a language limitation or have I missed something?

Background

There is support for using functions to default parameters in a pretty neat way:

> a = ({ no }, b = (function(c) { return c -1; })(no)) => console.log(no,b);
[Function: a]
> a({ no: 2 })
2 1

This could allow for passing results from expensive database calls while retaining the option of getting the parameters if null. This requires though that we can do an await inside the parameter call:

> a = async ({ no }, b = await (async function(c) { return c -1; })(no)) => console.log(no,b);
a = async ({ no }, b = await (async function(c) { return c -1; })(no)) => console.log(no,b);
                       ^^^^^

SyntaxError: 'await' is not a valid identifier name in an async function

I suppose that this is a feature from async/await being syntactic sugar for Promises and rewriting the above as a Promise would be rather challenging. Still, the pattern would be really neat and If I've missed something, please enlighten me.

Thanks!

like image 403
Max Gordon Avatar asked Mar 28 '18 07:03

Max Gordon


People also ask

Can await be used for async function?

The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or at the top level of a module.

Should await always be used with async?

Note: The await keyword is only valid inside async functions within regular JavaScript code. If you use it outside of an async function's body, you will get a SyntaxError .

Can async function take parameters?

An async function (or AyncFunction) in the context of Async is an asynchronous function with a variable number of parameters where the final parameter is a callback. An async function is also referred to as a “Node-style async function” or a “continuation passing-style function” (CPS).

Can we use await without promise?

This rule applies when the await operator is used on a non-Promise value. await operator pauses the execution of the current async function until the operand Promise is resolved.


1 Answers

It's a limitation, specifically in this case AwaitExpression is not allowed in CoverCallExpressionAndAsyncArrowHead (which includes the formal parameters). The second bullet point is:

  • It is a Syntax Error if CoverCallExpressionAndAsyncArrowHead Contains AwaitExpression is true.

...but the same language is present for the various other function definitions.

I probably don't have to tell you that you can work around this by just not awaiting the async function until within the body:

const a = async ({ no }, b = (async function(c) { return c -1; })(no)) => {
// Removed await ------------^
    b = await b; // <== Then added it back within the function body
    console.log(no,b);
};
a({no: 3});

Using an await expression in a default parameter is a fascinating thought. I suspect the reason it's not (yet?) allowed is primarily complexity management. (This is speculation on my part, take it with a grain of salt.) The beginning of an async function is synchronous (that's how you start your asynchronous operation, after all), it only becomes async as of the first await or return (or implicit return at the point of falling off the end of the function). Having it become async prior to the beginning of the function body adds a fair bit of complexity. Not that it couldn't be done. :-)

However, looking through the closed issues on the proposal, an issue was raised asking what happens when a default parameter initialization throws an exception, should it throw or return a rejected promise? Which led to a TC39 discussion in which it was determined that it should return a rejected promise, thus this issue, the resolution of which moved evaluation of the parameter initialization into the function body (so exceptions could be part of the promise). Which would seem, to my mind, to open up the possibility of allowing await in the formal parameters of an async function...

like image 196
T.J. Crowder Avatar answered Oct 24 '22 12:10

T.J. Crowder