# Concurrent Async and Normal Await Evaluation Blocks

**URL:** <https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [June 25, 2021, 1:24am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827 "2021-06-25T01:24:11Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![wlib](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/wlib/32/887_2.png) [@wlib](https://es.discourse.group/u/wlib)\
**Post date:** [June 25, 2021, 1:24am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/1 "2021-06-25T01:24:11Z")

</div>

## Summary

With promises, concurrency is already trivial to implement, but not in a syntactically clear way.  
I propose `async`/`await` blocks to alleviate this ergonomic disincentive.

## Motivation

If we have a variable dependency graph for `d(a, b, c.property)`:

```javascript
a b c
| | |
| | (c => c.property)
\ | /
  d

```

We can implement it intuitively like this:

```javascript
const a = getA()
const b = getB()
const c = getC()

d(a, b, c.property)

```

But what about when `a`, `b`, and `c` are promises?  
It could be translated directly from above like this:

```javascript
const a = await getA()
const b = await getB()
const c = await getC()

d(a, b, c.property)

```

But if we optimally implement this for the given dependency graph, we get this:

```javascript
const _a = getA()
const _b = getB()
const _c = getC()

const a = await _a
const b = await _b
const c = await _c

d(a, b, c.property)

// Or

const [a, b, c] = await Promise.all([
  getA(),
  getB(),
  getC()
])

d(a, b, c.property)

```

This is obviously enough of an obstacle to make people accidentally or carelessly serialize their concurrent code.

## Proposal

### `async` block

We need some syntax sugar here for `Promise.all` - and this is where I want some help with considerations.

I think the most obvious solution is this:

```javascript
async {
  const a = getA()
  const b = getB()
  const c = getC()
}

d(a, b, c.property)

```

Here, we have an "`async` block" that is unlike other blocks in that it is actually maintaining its scope.  
It evaluates its statements in a way that is only different in that it automatically `await`'s all expressions that are to be "called by value".  
An implementation might build a dependency graph of values, with the end of the `async` block being the end of the graph.  
Then, the graph is just reduced as if each node was independently `await`'ed.  
In essence, this is a way of opting into lazy evaluation.

### `await` block

The complement to the `async` block would be normal evaluation.  
This can be opted-into with an `await` block, which is most convenient  
when applied within an `async` block.

Here is an example of when it might make sense:

```javascript
async {
  const resultA = concurrentProcessA()
  concurrentProcessB()
  await {
    await concurrentProcessCStep1()
    await concurrentProcessCStep2()
    await concurrentProcessCStep3()
    console.log("The normal evaluation order we are used to")
  }
  concurrentProcessD()
}

```

## Discussion

Now, the scope of this proposal makes it fairly powerful, one may argue that this would completely change the language.  
If this change is seen as too much, I would happily settle for just a nice  
syntax sugar for `Promise.all`

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 25, 2021, 3:07am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/2 "2021-06-25T03:07:29Z")

</div>

[Here's](https://es.discourse.group/t/synchronous-exceptions-thrown-from-complex-expressions-create-abandoned-promises-solutions/663) a somewhat related thread. It was trying to solve a different problem, but a lot of the conversation revolved around different syntaxes for `Promise.all()`

---

<div class="post-metadata">

**Author:** ![wlib](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/wlib/32/887_2.png) [@wlib](https://es.discourse.group/u/wlib)\
**Post date:** [June 25, 2021, 3:38am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/3 "2021-06-25T03:38:09Z")

</div>

That was a great thread to read through as it began to overlap more and more with this - thanks! I think that we need, overall, better concurrency handling in the language. I'm sure my proposal would result in a lot of changes in the cores of js implementations, similar to the introduction of async/await. Even with that cost, I think, especially after reading that, that an opt-in "lazy evaluation" mode would be a really valuable evolution of the language.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [June 25, 2021, 11:29am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/4 "2021-06-25T11:29:01Z")

</div>

> [@wlib](#):
>
> If this change is seen as too much, I would happily settle for just a nice  
> syntax sugar for `Promise.all`

Perhaps this proposal would interest you: [GitHub - tc39/proposal-await.ops: Introduce await.all / await.race / await.allSettled / await.any to simplify the usage of Promises](https://github.com/tc39/proposal-await.ops)

```javascript
const [a, b, c] = await.all [getA(), getB(), getC()];

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 27, 2021, 3:19am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/5 "2021-06-27T03:19:12Z")

</div>

So, with your current proposal, how do you propose something like this works?

```javascript
async {
  const myArray = []
  myArray.push(asyncFn1())
  myArray.push(asyncFn2())
}

```

Is myArray allowed to have `[<result of asyncFn2()>, <result of asyncFn1()>]` when this is done executing? Why or why not?

---

<div class="post-metadata">

**Author:** ![Jonas\_Wilms](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jonas_wilms/32/189_2.png) [@Jonas\_Wilms](https://es.discourse.group/u/Jonas_Wilms)\
**Post date:** [June 28, 2021, 7:07pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/6 "2021-06-28T19:07:18Z")

</div>

I don't like this kind of magic. Reasoning about async code is already hard, having the language do the magic for you will make folks forget what happens under the hood, until it does not work as expected. I see the [same problem with Automatic Semicolon Insertion](https://brendaneich.com/2012/04/the-infernal-semicolon/).

> Here, we have an "`async` block" that is unlike other blocks in that it is actually maintaining its scope.

With `let` and `const` we finally had consistent block scoping in JS ... Just to break that now again?

> If this change is seen as too much, I would happily settle for just a nice  
> syntax sugar for `Promise.all`

Jup, that sounds like a good idea ...

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 28, 2021, 7:59pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/7 "2021-06-28T19:59:15Z")

</div>

I'm leaning towards a `Promise.all()` syntax too - I don't see a feasible way to implement a dependency-graph magic solution, in a way where it's easy to understand the order in which things will execute (though maybe I'm just not seeing it).

The only question is - what would a `Promise.all()` syntax look like? I think the biggest issue with `Promise.all()` is the fact that the assignment targets are so disconnected from the promises. e.g.

```javascript
const [var1, var2, var3] = await Promise.all([
  getA(),
  getB().then(x => x.y),
  getC(),
  doSomethingElse()
])

```

The fact that getC()'s result will eventually get assigned to var3 makes this code a little difficult to follow. So here's one possibility, just to throw something out there.

```javascript
parallel const
  var1 = await getA(),
  var2 = await getB().then(x => x.y),
  var3 = await getC(),
  _ = doSomethingElse()

```

`parallel const` will cause all of its declarations to be executed in parallel. The "\_" is a throwaway variable, for any expressions that don't need their result assigned to something.

Any thoughts? Or different ideas?

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [June 28, 2021, 9:48pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/8 "2021-06-28T21:48:39Z")

</div>

I have an idea :) And since I'm in the process of getting myself familiar with Babel internals, I've been working on a proof-of-concept parser patch and plugin. Not sure I'll be able to turn that into an actual proposal, but I may try if there's interest.

Instead of an async block as the OP, which is confusing to me because it looks like a scope but the variables bleed out, I declare individual async variables, and wrap every access in await:

```javascript
async function work() {
  async var a = afoo();
  async let b = asleep();
  async const c = alas();
  future d = awake(); // short for `async const`

  b = morework(b, c);
  return a.concat(b, d);
}

```

transpiles to:

```javascript
async function work() {
  var a = afoo();
  let b = asleep();
  const c = alas();
  const d = awake();

  b = morework(await b, await c);
  return (await a).concat(await b, await d);
}

```

Because I think `async const` is too long yet the most useful, I made `future` a contextual keyword equivalent to `async const`.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 28, 2021, 10:32pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/9 "2021-06-28T22:32:19Z")

</div>

Interesting idea. I'm not sure yet how I feel about variable access meaning different things depending on how it was defined - I'll have to set on this idea for a bit and see how it settles. I'm especially not crazy about the idea of being able to reassign to these special variables and having it preserve its specialness, without any marker at the reassignment site that this is happening - I think if this idea goes forwards, I would only want an `async const` (or `future`) version.

This proposal will also have some issues in node. In the transpiled code, if d rejects while we're still awaiting b, then node will stop the process because the promise was never awaited, and never had a catch handler attached (it didn't know we were planning on eventually awaiting it). But, there's ways to resolve that with how it's transpiled, it'll just be something to keep in mind.

...but this is actually an interesting point. Does this mean an exception can be thrown at the location of a variable access, because behind the scenes we're really implicitly awaiting a promise there?

And here's one potential oddity I can think of.

```javascript
future x = someAsyncTask()
// ...
const f = () => x
console.log(f())

```

I assume that these async variables can only be used inside of async functions, so that will just result in an early error.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [June 28, 2021, 11:16pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/10 "2021-06-28T23:16:13Z")

</div>

> [@theScottyJam](#):
>
> I'm not sure yet how I feel about variable access meaning different things depending on how it was defined

It's mere syntax sugar. Instead of typing await where you need the result, you type async where you're starting the computation.

> [@theScottyJam](#):
>
> reassign to these special variables and having it preserve its specialness

Preserving the specialness is the only sane option, if reassignment is allowed. Imagine conditionals. But yes, `future` was my initial idea, however AFAICT nobody's too eager to add new keywords, so I came with the alternative `async` prefix.

> [@theScottyJam](#):
>
> This proposal will also have some issues in node. In the transpiled code, if d rejects while we're still awaiting b, then node will stop the process because the promise was never awaited, and never had a catch handler attached (it didn't know we were planning on eventually awaiting it). But, there's ways to resolve that with how it's transpiled, it'll just be something to keep in mind.

Sounds great, that would mean it does more useful stuff than swapping one keyword for another.

> [@theScottyJam](#):
>
> Does this mean an exception can be thrown at the location of a variable access

Yes. That's not new: `{ console.log(x); let x; }`

That last point is correct: you basically have `await x` in sync function.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 28, 2021, 11:57pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/11 "2021-06-28T23:57:03Z")

</div>

> [@lightmare](#):
>
> Yes. That's not new: `{ console.log(x); let x; }`

Yeah, but doing that is a straight-up bug, while these thrown exceptions might make sense to catch. So, code like this might become prevalent.

```javascript
async function main() {
  future fileContents = readFile()
  future metadata = getMetadata()

  try {
    fileContents
  } catch (err) {
    if (err.code === 'FILE_NOT_FOUND') return null
    throw err
  }

  return { fileContents, metadata }
}

```

I'm not saying this is necessarily a bad thing, but it is different.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 29, 2021, 12:23am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/12 "2021-06-29T00:23:03Z")

</div>

I've thought of another scenario that `Promise.all()` doesn't handle very well, and neither of our proposed syntaxes will handle it well also. It would be nice if whatever syntax we come up with could also handle this scenario too.

```javascript
// Sync version
const getData = async () => ({
  name: getName(),
  birthday: getBirthday(),
  metadata: { id: getId() },
})

// Async version
async function getData() {
  const [name, birthday, id] = await Promise.all([
    getName(),
    getBirthday(),
    getId(),
  ])

  return {
    name,
    birthday,
    metadata: { id },
  }
}

```

**Edit:**

I think I figured out one potential syntax that could help with both use cases. We introduce an `await.multi` keyword. When executing an expression (or statement), and an `await.multi` gets hit, other parts of the expression will continue to execute, potentially causing more `await.multi`s to be hit. Once everything in the expression has been evaluated that is able to be evaluated, execution will pause until all promises have been resolved.

Some examples:

```javascript
const getData = async () => ({
  name: await.multi getName(),
  birthday: await.multi getBirthday(),
  metadata: { id: await.multi getId() },
})

const
  a = await.multi getA(),
  b = await.multi getB(),
  c = await.multi getC()

```

Note that nested `await.multi` won't be allowed, so you can't do this:

```javascript
const result = await.multi f(await.multi g())

```

**Edit 2:**

I'm realizing that `await.multi` doesn't make sense when bounded by most statements. It may just be that expressions and declarations are the only things that bound `await.multi`, and no other statement can be used to bound its effect.

(By "bound it", I'm talking about figuring out figuring out which `await.multi`s get grouped together into a single `Promise.all()` effect)

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [June 29, 2021, 9:08am UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/13 "2021-06-29T09:08:07Z")

</div>

I don't think `await.multi` is viable. Allowing it on arbitrary expressions would wreak havoc in evaluation order.

```js
r = [x(await.multi f()), y(), z(await.multi g())];

```

How should function calls be ordered?

- immediately call what you can in source order, then resolve the rest in source order:
  - `f, y, g, await.all, x, z`
  - `f, y, g, await f, x, await g, z`

- start `await.multi` first, then resolve everything in source order:
  - `f, g, await.all, x, y, z`
  - `f, g, await f, x, y, await g, z`

- start `await.multi` first, then resolve the rest as arguments become available:
  - `f, g, y, ... non-deterministic`

Moreover, `await.multi` cannot span across logical operators, conditional or comma operator:

```javascript
await.multi f(a) && await.multi f(b);
// should not start f(b) unless f(a) resolves to truthy value

await.multi f(t) ? await.multi f(a) : await.multi f(b);
// must first resolve f(t), then start either f(a) or f(b), not both

a = await.multi f(b), b = await.multi f(a);
// yuck

```

> [@theScottyJam](#):
>
> Note that nested `await.multi` won't be allowed, so you can't do this:
> 
> `const result = await.multi f(await.multi g())`

I don't see a problem here, there is clear topological order in which this can be resolved.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 29, 2021, 1:44pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/14 "2021-06-29T13:44:56Z")

</div>

> [@lightmare](#):
>
> How should function calls be ordered?

This one is the answer:

> [@lightmare](#):
>
> f, g, await.all, x, y, z

I think there isn't an issue as long as we define a clear, deterministic, and predictable ordering to it all, but you're right that this having a different execution order is probably the number one issue with this idea.

But, here's how a clump of `await.multi` transpiles:

```javascript
const getData = async () => ({
  name: await.multi getName(),
  birthday: await.multi getBirthday(),
  metadata: { id: await.multi getId() },
})

// is the same as

const getData = async () => {
  const [$temp1, $temp2, $temp3] = await Promise.all([
    getName(),
    getBirthday(),
    getId(),
  ])
  return {
    name: $temp1,
    birthday: $temp2,
    metadata: { id: $temp3 },
  }
}

```

You just extract all `await.multi` expressions and execute them first, then you execute everything else.

So, to address your other concerns:

> [@lightmare](#):
>
> Moreover, `await.multi` cannot span across logical operators, conditional or comma operator:

It can span across logical operators, conditionals, and the comma operator. As long as we understand that every `await.multi` expression executes before everything else in the expression, it should be clear what all of these examples do.

```javascript
await.multi f(a) && await.multi f(b);
// Both f(a) and f(b) will be called and executed in parallel. We'll `&&` the results.

// This doesn't completely defeate short-circuiting
// it just means you can't short-cuircut anything inside `await.multi`
// because they have to execute first.
// But here's another example that short cuircuits the g() call
await.multi f(a) && g(await.multi f(b));

await.multi f(t) ? await.multi f(a) : await.multi f(b);
// Similarly, f(t), f(a), and f(b) will all execute at the same time, then the results are placed into this ternary operator

let a, b;
a = await.multi f(b), b = await.multi f(a);
// Yes ... this one's a bit unfortunate, but it still makes sense.
// `f(b)` executes first and b is undefined.
// Then `f(a)` executes and a is undefined.
// The results of the two function calls are placed into the expression,
// and the rest of the expression is executed.

```

I can see the concern (especially since I didn't put too much thought into this specific issue until you pointed it out - thanks), but I think that overall, it's not too difficult to understand what's going on. To understand any expression with `await.multi`, first just understand that whatever `await.multi` expressions exist will execute first, then everything else will execute.

> [@lightmare](#):
>
> > [@theScottyJam](#):
> >
> > Note that nested `await.multi` won't be allowed, so you can't do this:
> > 
> > > `const result = await.multi f(await.multi g())`
> 
> I don't see a problem here, there is clear topological order in which this can be resolved.

Well, whether this should be allowed or not can be discussed. I just thought it'll be easier to understand if we make it so all `await.multi` within a single expression execute at the same time, instead of allowing multi-step `await.multi`s to exist. But maybe this isn't all that confusing, and it could be allowed.

- first g() executes, because it's in an `await.multi`. The other `await.multi` expression does not execute yet, because it depends on the result of the first.
- g() eventually resolves and was the only dependency of the outer `await.multi`, so we can now evaluate the outer `await.multi` expression, calling f() with g()'s result.
- Finally `const result = <result of outwer await.multi>` executes.

---

<div class="post-metadata">

**Author:** ![mmm211](https://avatars.discourse-cdn.com/v4/letter/m/f17d59/32.png) [@mmm211](https://es.discourse.group/u/mmm211)\
**Post date:** [June 29, 2021, 2:23pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/15 "2021-06-29T14:23:48Z")

</div>

How about allowing `Promise.all` to accept and return an object

```
async function getData() {
  const o = await Promise.all({
    name: getName(),
    birthday: getBirthday(),
    id: getId(),
  })

  return {
    o.name,
    o.birthday,
    metadata: { o.id },
  }
}
```

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [June 29, 2021, 2:35pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/16 "2021-06-29T14:35:06Z")

</div>

[https://github.com/ajvincent/proposal-await-dictionary](https://github.com/ajvincent/proposal-await-dictionary)

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [June 29, 2021, 6:47pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/17 "2021-06-29T18:47:26Z")

</div>

> [@theScottyJam](#):
>
> It can span across logical operators, conditionals, and the comma operator. As long as we understand that every `await.multi` expression executes before everything else in the expression, it should be clear what all of these examples do.

I see. It felt counter-intuitive at first; but as a two-pass process it makes sense.

---

<div class="post-metadata">

**Author:** ![Clemdz](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/clemdz/32/813_2.png) [@Clemdz](https://es.discourse.group/u/Clemdz)\
**Post date:** [July 5, 2021, 4:55pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/19 "2021-07-05T16:55:12Z")

</div>

This is an interesting topic! :)

I've been thinking about it recently, and I'd like to give it a try too.

So if I understood correctly, there are actually two main features to be discussed here:

- having a non-blocking `await`-like syntax inside async functions
- having some syntactic sugar for grouping several promises to be handled at the same time

Both those features combined would allow us to create a nice `Promise.all` syntactic sugar, but those could be treated separately (and that's what I'm going for here).

## Non blocking `await`-like syntax

I really like the `async const myVar = myPromise()` syntax idea.

However, I would rather place the `async` keyword after the `=` sign, like this:

```javascript
const myVar = async myPromise();

```

This would have the following pros:

- The parallel with the `await` syntax would be greater:

- This would also allow to use this `async` syntax without having to declare variables, like:

```javascript
async function () {
  async updateDB( /*...*/ );
  async fetch( /*...*/ );
}

```

One could argue that in that case, we could simply write instead:

```javascript
async function () {
  updateDB( /*...*/ );
  fetch( /*...*/ );
}

```

But here is the big difference: using `async` when calling the promises would ensure that those promises have settled before the wrapping async function resolves.  
This is the important point here, so that the language does not become a spaghetti mess of aynsc-resolving variables. Every promises called using `async` have to settle before the return statement of the function gets executed.

Also, compared to the version without `async`, this keyword gives a nice little indication that the function that is called is actually a promise, and not a regular function call.

### Deshugared syntax

Taking the simple following code:

```javascript
async function () {
  const a = async getA();
  const b = async getB();
  /* ... */
  return a + b;
}

```

the desugared version would more or less looks like this:

```javascript
async function () {
  let a;
  const _aPromise = getA().then(value => a = value);
  let b;
  const _bPromise = getB().then(value => b = value);
  /* ... */
  await _aPromise;
  await _bPromise;
  return a + b;
}

```

However, in this desugar version, we have to use `let` instead of `const` for variable declaration. This would a limitation of the desugared version only, in the real implementation, using `const` for async variable declaration should be possible.

Also, when awaiting the resolved value, there is the question whether the variable should be set to `undefined`, or left undeclared. If the variable can be declared using const, it makes sense that it stays undeclared, as setting the value to `undefined` and then updating to the resolved value would not be coherent with the `const` declaration.

### Rewriting `Promise.all`

At this point, we can already recreate our `Promise.all` example:

```javascript
async function () {
  let a, b, c;
  // Await the settlement of every promise inside this async function
  await (async () => {
    // Using the async keyword, so that the three promise get executed in parallel
    a = async getA();
    b = async getB();
    c = async getC();
    // As we are using the async keyword for the promises above
    // we have to wait for them before leaving the async function
  })();
  // Here, we know for sure that a, b, and c have settled
  d(a, b, c.property);
}

```

We could also imagine more complex examples:

```javascript
// Same as before, but let's get `a` using the fetch api
async function () {
  let a, b, c;
  await (async () => {
    async (async () => {
      const response = await fetch("url");
      a = await response.json();
    })();
    b = async getB();
    c = async getC();
  })();
  d(a, b, c.property);
}

```

The problem here is that creating wrapper promises isn't really readable.  
Also, variables created inside the wrapper promises aren't accessible in the parent scope.  
About this second point, we could instead write:

```javascript
async function () {
  const { a, b, c } = await (async () => {
    const a = async (async () => {
      const response = await fetch("url");
      return await response.json();
    })();
    b = async getB();
    c = async getC();
    return { a, b, c };
  })();
  d(a, b, c.property);
}

```

This fixes the issues of variable access, but this is even more difficult to read!

## Grouping promises

Here comes the second point of the topic. It would be great to have a dedicated syntax to group `await` and `async` promise calls together.

This syntax would need:

1. to be short and readable
2. to have scope coherence and consistency with the language. It could either:

- create a new scope, and have a way to return / expose variables to the outside scope
- do not create a new scope, and any created variables are directly accessible in the current scope

The difficulty about this point is to find a good syntax that meet these two necessary conditions.

As you initialy proposed, we could use `{ }` to create `await` and `async` block.  
(Here I'm changing the meaning you originally gave them, so that their behavior is the same as their "keyword" version)

Here is the definition of the `await` block:

```javascript
await {
  /* ... */
}
// instead of
await (async () => {
  /* ... */
})();

```

and here is the definition of the `async` block:

```javascript
async {
  /* ... */
}
// instead of
async (async () => {
  /* ... */
})();

```

So if we take back our last example, it would become:

```javascript
async function () {
  let a, b, c;
  await {
    async {
      const response = await fetch("url");
      a = await response.json();
    };
    b = async getB();
    c = async getC();
  };
  d(a, b, c.property);
}

```

However, this solution feels incomplete, because we have to declare variables outside the blocks, using the `let` keyword.

### Other ideas ?

We could also go for various other syntax, like the following one which does not create a new scope, thus any created variable is accessible anywhere in the function scope:

```javascript
async function () {
  await.{
    async.{
      const response = await fetch("url");
      const a = await response.json();
    }
    const b = async getB();
    const c = async getC();
  }
  d(a, b, c.property);
}

```

However, the `.{ }` syntax is not used anywhere else in the language, and this looks quite weird.  
I'm still presenting this idea, in case of it can inspire someone for something better, but I would personally not go for this one :)

Here is a last idea:

```javascript
async function () {
  await (
    async (
      const response = await fetch("url");
      const a = await response.json();
    );
    const b = async getB();
    const c = async getC();
  );
  d(a, b, c.property);
}

```

Here, using parentheses makes it clear that we are not creating a new scope, and that the variables are accessible anywhere in the function.  
However, it looks quite strange too, as it is not something we can already do in the language. Like the previous idea, I do not quite like this solution, I'm just sharing it in case it appeals to someone!

## To conclude

The `async` keyword used as a non-blocking `await` keyword could be quite versatile and powerful, but it could also mess up the language by making it even more complex to understand. What do you think about it?

Also, such an `async` keyword would be quite limited if it does not come along with a way to group certain promises together, because creating wrapper async functions is quite heavy and difficult to read.

However, finding a great syntatic sugar for this is complicated.  
So if someone has some ideas, please share them! :)

(and more generally, please feel free to share your thoughts about all of this!)

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [July 5, 2021, 6:24pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/20 "2021-07-05T18:24:06Z")

</div>

@Clemdz - interesting idea.

Finding an intuitive syntax for promise.all() is much harder than it sounds :p

So, in your proposal, when you use async on a promise, at what location does the await actually happen? Right before the target variable gets used? What if you do something like "const x = async f() + async g()", when do these get awaited?

---

<div class="post-metadata">

**Author:** ![Clemdz](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/clemdz/32/813_2.png) [@Clemdz](https://es.discourse.group/u/Clemdz)\
**Post date:** [July 7, 2021, 5:50pm UTC](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827/21 "2021-07-07T17:50:14Z")

</div>

That an interesting question you are asking there! :)

But before trying to answer to it, I'd just like to propose a new idea for the `await` / `async` block syntactic sugar, inspired right from this [very recent topic](https://es.discourse.group/t/values-from-scoped-blocks-does-proposal-exist/844) about returning values from a block! :)  
(I'm doing this right now, so that I'll be able to use this syntax later in my explanations)

## New syntax proposal for `await` / `async` blocks

As discussed in the aforementioned topic, the proposed `do { }` block is returning the last expression value:

```javascript
const foo = do {
  const x = f();
  const y = g();
  x + y
}
// foo will be equal to x + y

```

So actually, why couldn't we apply the same concept to `await` and `async` blocks?

```javascript
const foo = await {
  const x = async f();
  const y = async g();
  // wait before returning that x and y settle
  x + y;
}
// foo will be equal to: x + y

const bar = async {
  const x = await f();
  await g(x);
}
// bar will be equal to: await g(x)

```

This would be as simple as that!

So let's try answering your question about combining asyncs in a same expression!

## A solution to your question

Let's take the example you gave in your question:

```javascript
const x = async f() + async g();

```

Here, we are not only _setting_ an async value, but we are also trying to _get_ the value, in order to do some operations with it. However, as the first `async f()` has not settled yet at the time of the operation, we actually should get a `ReferenceError`, in the same spirit like when we try to use an undeclared variable.

Rewriting your example like this:

```javascript
const tmp1 = async f();
const tmp2 = async g();
const x = tmp1 + tmp2;

```

it become clear that we are trying to use async variables that may not have resolved.

So instead, you would have to write:

```javascript
const x = async {
  const tmp1 = async f();
  const tmp2 = async g();
  // wait for tmp1 and tmp2 to settle before returning from the scope
  tmp1 + tmp2;
}

```

or actually, even simpler:

```javascript
const x = async {
  // wait for both asyncs settle before returning from the scope
  async f() + async g();
}

```

So this would be almost the same code as your given example, but with an wrapper `async` block, indicating where the f() and g() have to be resolved so that we can continue without any problem, and assign `x` to the sum of their value.

## Personnal thoughts about this

This is the most minimal and coherent answer I can give you using the premises I defined in my own proposal. However, I have to admit I don't really like in the first place the concept of: "you can't access the value of an async variables, except when it is the last returned instruction of a scope, there you can use their value as if their were normal variables".

It makes sense why this is a thing within the whole idea I'm trying to propose, but I'm afraid this might actually not be very intuitive when writing or reading code. People might just be confused why is this possible to write `async f() + async g()` in some places, and not in some others. The new block syntax I'm proposing makes it even more confusing, because no `return` keyword is even here to explicitly indicate we are actually in a return expression.

Actually, waiting for async variables to settle would make way more sense if we are waiting right before leaving the scope of the function, and not just before we execute the last expression of it. Like this, every expression of the scope would be treated as equal: you can't access an async variable value because it could still be undeclared (and it would throw a _ReferenceError_). No matter if it is a return expression or not.

So with this new approach in mind, this would look like:

```javascript
let tmp1;
let tmp2;
async {
  tmp1 = async f();
  tmp2 = async g();
  // Return nothing here
  // Wait just before the block that tmp1 and tmp2 have settled
}
const x = tmp1 + tmp2;

```

The only con of this approach, and that's why I didn't proposed it in the first place, is that it does not allow to return the value of the inner async variables to the outer scope. At least not without implementing some new syntax just for this. So we have to declare our variables directly in the outer scope, using `let` instead of `const`. Yikes.

So in the end I am with two possible approaches:

1. awaiting before the return expression: it it easy to use, but might be too confusing
2. awaiting just before leaving the scope: it is not confusing at all, but is much less easy to use

This leads me to the following two questions:

1. What do you think about the 1st approach? Do you think it is too much confusing, or not confusing at all, or maybe something in the middle?
2. What are your thoughts about this 2nd approach, and do you see any way to improve it so that it become usable?

So actually I'm sorry @theScottyJam, in the end I'm answering your question by raising two of them!

Indeed, finding an intuitive syntax for `promise.all()` is much harder than it sounds! :)

[Next page](https://es.discourse.group/t/concurrent-async-and-normal-await-evaluation-blocks/827.md?page=2)
