Proposal: `await.all {...}` for parallelism

Jacob Bloom mr.jacob.bloom at gmail.com
Thu Nov 21 17:01:17 UTC 2019


>```javascript
>const promises = [...]
>await.all promises //returns an array of results
>await.race promises //returns a single result
>```

One of the goals of this proposal is to simplify the process of
collecting the promises in an array and then having to get them out of
another array.

>Why not just use a combination of `async`/`await` and `.then`?

That's an okay solution, though we still end up having to maintain
"parallel lists" of promises and values, which I'm hoping to avoid.
But you can sidestep them with something like this, which isn't too
bad:

```javascript
async function initialize() {
    let foo, bar, baz;
    await Promise.all([
        request('foo.json').then(t => foo = t.data),
        request('bar.json').then(t => bar = t.data),
        request('baz.json').then(t => baz = t.data),
    ]);
    render(foo, bar, baz);
}
```

On Thu, Nov 21, 2019 at 3:29 AM Naveen Chawla <naveen.chwl at gmail.com> wrote:
>
> I have a solution for that:
>
> const promises = [...]
> await.all promises //returns an array of results
> await.race promises //returns a single result
>
> etc.
>
> On Thu, 21 Nov 2019 at 09:51, manuelbarzi <manuelbarzi at gmail.com> wrote:
>>
>> AFAIK `await` can only accept an `expression` as a `Promise`, not other thing: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
>>
>> On Thu, Nov 21, 2019 at 10:46 AM Jacob Bloom <mr.jacob.bloom at gmail.com> wrote:
>>>
>>> >why not just `await` as already is, but supporting an
>>> >iterable / array of promises, as `Promise.all` already does
>>>
>>> `await` can already accept a non-promise, so I believe that'd be
>>> breaking syntax if `Array.prototype.then` is set. It also requires
>>> collecting the promises in an array, which is what the proposed syntax
>>> is trying to avoid.
>>>
>>> On Thu, Nov 21, 2019 at 2:41 AM Jacob Bloom <mr.jacob.bloom at gmail.com> wrote:
>>> >
>>> > >Just FYI, I previously suggested a couple things substantially more
>>> > >flexible than this
>>> >
>>> > Ah, thank you for bringing those proposals to my attention. I looked
>>> > through the archives for relevant discussions but I must've missed
>>> > them.
>>> >
>>> > It seems like we converged on a similar syntax for what you called
>>> > "merging," and the idea that there ought to be a separate syntax for
>>> > iteration. I don't know whether that means that this is the right
>>> > solution or just the most obvious one, but either way it's encouraging
>>> > to know that other people have the same difficulties with the current
>>> > syntax and are thinking about the problem.
>>> >
>>> > >from my experience, committee members are in general
>>> > >very hesitant to add syntax for anything that doesn't pay for
>>> > >itself well
>>> >
>>> > Yeah, I figured the bar would be high for new syntax. I've run into
>>> > the awkwardness of dealing with distinct parallel tasks several times,
>>> > and a few of the people I discussed it with were in the same boat, so
>>> > I wrote up this proposal thinking it might have a wide appeal. The
>>> > proposed syntax desugars via a relatively simple transformation but
>>> > encourages developers to reason about the problem in a completely
>>> > different way that I'd argue is more intuitive. Whether the committee
>>> > agrees and thinks it justifies a new syntax remains to be seen, but
>>> > either way I'm excited to see where this discussion goes (whether it
>>> > leads to the proposed syntax, to some other syntax, or to somewhere
>>> > else entirely).
>>> >
>>> > As a side note: thank you to everyone for the thoughtful questions and
>>> > responses, I had no idea what to expect from this thread and it's gone
>>> > better than I could've hoped for. Thank you for not immediately
>>> > shooting down a proposal that looks similar to other proposals before
>>> > it.
>>> >
>>> > On Wed, Nov 20, 2019 at 7:36 PM Isiah Meadows <contact at isiahmeadows.com> wrote:
>>> > >
>>> > > Just FYI, I previously suggested a couple things substantially more
>>> > > flexible than this [1] [2] (originated from this [3]), and it mostly
>>> > > fell flat due to being highly premature. Anything exclusive to
>>> > > promises is unlikely to win as library methods exist for basically all
>>> > > use cases and from my experience, committee members are in general
>>> > > very hesitant to add syntax for anything that doesn't pay for itself
>>> > > well. Similar questions have come up a few times in the past, too, and
>>> > > I've commented on two of them. [4] [5]
>>> > >
>>> > > If anything, I don't feel we know the problem space well enough, and
>>> > > the language lacks the primitives needed to really dig into it. (This
>>> > > is why I came up with my generator forking strawman. [6])
>>> > >
>>> > > [1]: https://github.com/isiahmeadows/non-linear-proposal
>>> > > [2]: https://github.com/isiahmeadows/lifted-pipeline-strawman
>>> > > [3]: https://esdiscuss.org/topic/observable-promise-parallel-control-flow-proposal
>>> > > [4]: https://esdiscuss.org/topic/stream-async-await
>>> > > [5]: https://esdiscuss.org/topic/improved-syntax-for-observable-mapping-and-subscribing
>>> > > [6]: https://github.com/isiahmeadows/proposal-generator-fork
>>> > >
>>> > > -----
>>> > >
>>> > > Isiah Meadows
>>> > > contact at isiahmeadows.com
>>> > > www.isiahmeadows.com
>>> > >
>>> > > On Wed, Nov 20, 2019 at 6:16 PM Jacob Bloom <mr.jacob.bloom at gmail.com> wrote:
>>> > > >
>>> > > > ...strike that, I misread the "but that still waits for the async
>>> > > > functions to complete" part. So what you're proposing is that
>>> > > > everything functions normally inside the curly braces, but execution
>>> > > > doesn't continue until all promises have resolved? So your example
>>> > > > would work essentially like this:
>>> > > >
>>> > > > ```javascript
>>> > > > const x = doSomethingAsync();
>>> > > > const y = doSomethingElseAsync();
>>> > > > await x, await y;
>>> > > > // all promises are resolved by now, but
>>> > > > // still need to use await to unbox the values
>>> > > > someFunction(await x, await y);
>>> > > > ```
>>> > > >
>>> > > > On Wed, Nov 20, 2019 at 3:28 PM Jacob Bloom <mr.jacob.bloom at gmail.com> wrote:
>>> > > > >
>>> > > > > >Maybe if you drop the "await" in your example:
>>> > > > > >
>>> > > > > >```javascript
>>> > > > > >await.all {
>>> > > > > >    const x = doSomethingAsync();
>>> > > > > >    //x is just the promise here
>>> > > > > >}
>>> > > > > >```
>>> > > > > >
>>> > > > > >...but that still waits for the async functions to complete, I think it would
>>> > > > > >cause fewer bugs and would seem to still satisfy the motivation?
>>> > > > >
>>> > > > > It doesn't seem like the `await.all` block is doing anything in that
>>> > > > > case. That code seems equivalent to this:
>>> > > > >
>>> > > > > ```javascript
>>> > > > > const x = doSomethingAsync();
>>> > > > > myFunction(await x)
>>> > > > > ```
>>> > > > >
>>> > > > > >```javascript
>>> > > > > >await.all {
>>> > > > > >  const x = await doSomethingAsync();
>>> > > > > >  //x is still undefined here!
>>> > > > > >}
>>> > > > > >```
>>> > > > >
>>> > > > > You bring up a good point about scoping and race conditions. It's a
>>> > > > > little tricky since the curly braces create a block scope but none of
>>> > > > > the parallel statements should be allowed to access each-other's
>>> > > > > variables, it's almost like each statement should have its own scope.
>>> > > > > Maybe it'd be better to have a syntax that ensures a set of curly
>>> > > > > braces for each parallel task? Async do-expressions could be a good
>>> > > > > solution (assuming they'd work kind of like an async IIFE):
>>> > > > >
>>> > > > > ```javascript
>>> > > > > async function initialize() {
>>> > > > >   let foo, bar, baz;
>>> > > > >   await Promise.all([
>>> > > > >     async do { foo = (await request('foo.json')).data },
>>> > > > >     async do { bar = (await request('bar.json')).data },
>>> > > > >     async do { baz = (await request('baz.json')).data },
>>> > > > >   ]);
>>> > > > >   render(foo, bar, baz);
>>> > > > > }
>>> > > > > ```
>>> > > > >
>>> > > > > (this is also a less drastic syntax change that piggybacks on an
>>> > > > > existing proposal)
>>> > > > >
>>> > > > > On Wed, Nov 20, 2019 at 11:50 AM Bergi <a.d.bergi at web.de> wrote:
>>> > > > > >
>>> > > > > > Hello!
>>> > > > > >
>>> > > > > > > This [current] structure is also just fundamentally different from working
>>> > > > > > > serially in async/await and it forces you to reason about the problem
>>> > > > > > > in a specific way. This doesn't appear to be a conscious decision to
>>> > > > > > > force good code practices
>>> > > > > >
>>> > > > > > Actually I'd argue that it is. Doing stuff concurrently *is*
>>> > > > > > fundamentally different from doing it serially, and should be reasoned
>>> > > > > > about every time you use it.
>>> > > > > >
>>> > > > > > kind regards,
>>> > > > > >  Bergi
>>> > > > > > _______________________________________________
>>> > > > > > es-discuss mailing list
>>> > > > > > es-discuss at mozilla.org
>>> > > > > > https://mail.mozilla.org/listinfo/es-discuss
>>> > > > _______________________________________________
>>> > > > es-discuss mailing list
>>> > > > es-discuss at mozilla.org
>>> > > > https://mail.mozilla.org/listinfo/es-discuss
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list