Skip to content

Latest commit

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Asynchronous Blocks

ECMAScript proposal, specs, tests, and reference implementation for Asynchronous locks

This initial proposal was drafted by @johnhenry with input from @_ and @_.

Designated TC39 reviewers: @_ @_

Table of Contents

Status

This proposal is currently at stage 0 of the process.

Prior Art

Some of the syntaxes in this proposal, namely the "do await" syntax, have been discussed before

Rationale and Motivation

Previously, in order to preform a one-off task within a program that didn't affect the global scope, one had to use an Immediately Invoked Function Expression (IIFE).

(function(){consta=1;console.log(a);//other stuff...})();(function(){consta=2;console.log(a);//other stuff...})();//logs "1", "2";

With blocks and blocked scoped variables, introduced for 2015, the syntax becomes much cleaner.

{consta=1;console.log(a);//other stuff}{consta=2;console.log(a);//other stuff}console.log(a);//logs "1", "2";

Currently if we want to invoke as asynchronous expression, set to be introduced for 2017 we must resort to using an IIFE once more.

(asyncfunction(){consta=awaiteventually(1);//other stuff...})();(asyncfunction(){consta=awaiteventually(2);//other stuff...})();//logs eventually "1", "2" or "2", "1"

Alternatively, we can use non-anoymous functions and invoke them later in the program:

constmain=asyncfunction(){consta=awaiteventually(1);//other stuff...};constmain2=asyncfunction(){consta=awaiteventually(2);//other stuff...}main();main2();//logs eventually "1", "2" or "2", "1"

but this is still not as elegant as one might hope.

Proposed Solution: Asynchronous Blocks

We can make this cleaner by implementing asynchronous blocks

async{consta=awaiteventually(1);console.log(a);//other stuff}async{consta=awaiteventually(2);console.log(a);//other stuff}//logs eventually "1", "2" or "2", "1"

Asynchronous blocks are executed asynchronously with respect to the surrounding context and allow use of the "await" keyword without having to create another functional scope.

other operators

This would work in conjunctions with other operators that come before blocks:

####for/for-in/for-of

constfor(constiof[1,2])async{awaiteventually(i);}console.log(0);//logs "0"//logs eventually "1", "2"

for-await-of

See Asynchronous Iterator Proposal

async{forawait(constiofeventuallyIterator(1,2))async{console.log(i);}console.log(0);}//logs "0"//logs eventually "1", "2"

while

while(true)async{awaiteventually(i++);}console.log(0);//logs "0"//logs eventually "1", "2"...

do

See Do-Expression Proposal

constresult=doasync{consta=1;}result.then(console.log.bind(console));//logs eventually "1"

Asynchronous blocks

When Number.prototype[Symbol.iterator] is called, the following steps are taken:

  • While parsing, if the keyword "async" is encountered directly before a block, execute that block's contents asynchronously with respect to the surrounding program.
  • That block will now have the "await" keyword available at the top level.
  • Declarations using keywords "let" and "const" would not affect the scope outside of the asynchronous block.
  • Keeping in mind backward compatibility, declarations using the keyword "var", along with naked declarations, would affect the scope outside of the asynchronous block.

transformation

The following transformation recursively on a string:

constmatch=/^async\s*{\s*(.*)\s*}/m;constwrap=(code)=>`(async function(){${code}})()`;exportdefault(code)=>{returnmatch.test(code) ? wrap(code.match(match)[1]) : code;};

would have the following result:

async { ... } -> (asyncfunction(){ ... })()

Although, it misses the requirement regarding "backward compatibility" above in that it does not respect the use of the "var" keyword.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors