it would be nice to have async-blocks like ``async {some_statements}`` and ``async (some_expression)``

# Igor Baklan (7 months ago)

I looks like it would be nice to have async-block which might be alias to async-lambda immediate invocation, so that:

var promise = async { /*some statements with await*/ };

<==>

var promise = (async () => { /*some statements with await*/ }) ();

and

var promise = async ( /*some statements with await*/ );

<==>

var promise = (async () => ( /*some expression with await*/ )) ();

Then it can gave some convenience in writing some semi-async function, like for example parallel async batch processing, which might look like:

const backupBatch = (batch) => {
  var tasks = [];
  for (let item of batch) {
    tasks.push(
      async {
        const content = await readContent(item);
        await writeContent(item + ".bak", content);
      }
    )
  }
  return Promise.all(tasks)
}

or like

const backupBatch = (batch) => {
  var tasks = [];
  for (let item of batch) {
    tasks.push(
      async (
        await writeContent(item + ".bak", await readContent(item));
      )
    )
  }
  return Promise.all(tasks)
}

of course this simplistic case can be rewritten without async-block like:

const backupBatch = (batch) => {
  return Promise.all(
    batch.map(
      async (item) => (
        await writeContent(item + ".bak", await readContent(item));
      )
    )
  );
}

However I believe this not reduce usefulness of initial async-block construction.

Also it should be mentioned that this idea "isn't new", something very similar I saw in [async-do] comment.

And finally, if this construct will be introduced, it will provide some nice symmetry - of whether you put async keyword in function header definition, or at the very beginning of its body, like:

const asyncFunc = async (/*args*/) => {/*function body with await-s*/};

<==>

const asyncFunc = (/*args*/) => { return async {/*function body with await-s*/} };

<==>

const asyncFunc = (/*args*/) => ( async {/*function body with await-s*/} );

And

const asyncFunc = async (args) => (some_async_expression);

<==>

const asyncFunc = (args) => async (some_async_expression);

By the way parentheses hear (in async(...)) might be essencial, for example for following case: async x => x != async (x => x), cause first evaluates into async-function, while the second should be evaluated into completed promise which value is sync function (x => x).

# Jordan Harband (7 months ago)

That would create a refactoring hazard if i had the block: { a(); b(); return c(); } and stuck the async keyword in front of it - suddenly the function wouldn't have an early completion in the block, it'd create and throw away a Promise.

# Jeremy Martin (7 months ago)

That would create a refactoring hazard if i had the block: { a(); b(); return c(); } and stuck the async keyword in front of it [...]

That's a pretty specific keyword to slip in before a given code block - is that really much of a real-world risk?

Also worth noting that the grammar here would have to preclude newlines between async and the opening bracket. This is already perfectly valid JavaScript:

var async = 'gotcha'

var promise = async

{ console.log('hi!') }

That being said, this probably doesn't really make sense on it's own, but could definitely build on top of do/let blocks or lamdas (<-- not really current with the state of affairs on any of that).

# Alan Johnson (7 months ago)

I’m all for the async block. In Scala, there actually are no async functions; only async blocks. (Technically, this isn’t in the language; it’s a macro from a library called scala-async scala/async.) This works out a bit more nicely because it’s expression-oriented to begin with.

But the nice thing about async blocks is that you can then use promise combinators within a function that might compose a couple different async operations. This might be a little less necessary in Javascript though, since it is rather flexible on the typing of promise-related functions; it will promote values to promises where necessary and flatten nested promises. Often in Scala, I’ll wrap a normal value in an async to make it a Future (Scala’s Promise).

# Oli Lalonde (7 months ago)

This proposal sounds a bit like do-expressions but with async support? babeljs.io/docs/plugins/transform-do-expressions If that's the case, why not async do { /*....*/ }?

# Igor Baklan (7 months ago)

As I've mentioned in initial post

this idea "isn't new", something very similar I saw in [async-do] comment

So answer yes - it actually the same idea. However as for me do part is quite optional and can be omitted without any lost (in this construct). Meaning that if we will introduce different variations of so called "do {...}" statement in future, they not mandatory should share do keyword (they rather should only share the same "spirit").