The current way to write what you want is:

await Promise.all(itemsCursor.map(item => db.insert(item));

or

await Promise.all(itemsCursor.map(Promise.guard(5, item =>
db.insert(item))));

if you are using a library like `prfun` (
https://github.com/cscott/prfun#promiseguardfunctionnumber-condition-function-fn--function
).

I'm not sure adding a new parallel loop construct is an obvious improvement
on this, especially since unguarded concurrent execution is usually a
mistake (can cause memory requirements to blow up), as you point out
yourself.

I'd be more in favor of new syntax if it was integrated with a
work-stealing mechanism, since (a) that can't as easily be done in a
library function (you need access to the entire set of runnable tasks, not
just the ones created in this loop), and (b) is more likely to be
correct/fast by default and not lead to subtle resource-exhaustion problems.
  --scott

On Fri, Sep 6, 2019 at 12:40 PM Tom Boutell <[email protected]> wrote:

> *Specifying concurrency for "for...of" loops potentially containing
> "await" statements in the loop body*
>
> In the async/await era, I see most developers using the async and await
> keywords in 90% of situations, shifting to "Promise.all" or the bluebird
> library only to cope with concurrency issues.
>
> The most common case in my experience is the need to admit a manageable
> level of parallelism when iterating a large array (or iterator, see the
> final section) and performing asynchronous work on each item. Unlimited
> concurrency (Promise.all) tends to overwhelm backends involved in a way
> that confuses developers as to what is happening. Bluebird's "Promise.map"
> permits concurrency to be specified, which is great, but requires pulling
> in a library and switching of mental gears ("OK right, these async
> functions return promises," etc).
>
> To build on the friendliness of async/await, I propose these two syntaxes
> be accepted:
>
> SYNTAX ONE
>
> ```js
> for (item of items concurrent) {
>   // db.insert is an async function
>   await db.insert(item);
> }
> ```
>
> In Syntax One, all loop bodies commence concurrently (see below for the
> definition of "concurrently" with regard to async). If an exception is not
> caught inside the loop, it is thrown beyond the loop, and all exceptions
> subsequently thrown by concurrently executing loop bodies are discarded
> (like Promise.all).
>
> *While I feel that unlimited concurrency is usually a mistake in a
> situation where you have an array of items of unpredictable number, it
> seems odd not to have a syntax for this case, and "concurrency 0" seems
> clunky.*
>
> SYNTAX TWO
>
> ```js
> for (item of items concurrency 5) {
>   // db.insert is an async function
>   await db.insert(item);
> }
> ```
>
> in Syntax Two, up to 5 loop bodies commence concurrently (see below).
> There is no guarantee that item 3 will finish before item 2, or that item 4
> won't start (due to 3 being finished) before item 2 ends, etc. If an
> exception is not caught inside the loop, it is thrown beyond the loop, and
> all exceptions subsequently thrown by concurrently executing loop bodies
> are discarded (like Promise.all in this respect, except for the restriction
> of concurrency).
>
> DEFINING CONCURRENCY FOR ASYNC
>
> For purposes of this proposal, "concurrent" execution means that multiple
> loop bodies may be suspended via "await" at any given time. It does NOT
> refer to multithreaded execution, worker threads, etc.
>
> CONSIDERATIONS FOR ASYNC ITERATORS
>
> Async iterator syntax for "for...of" loops, as in:
>
> ```js
> for await (item of itemsCursor) { ... }
> ```
>
> Should also support concurrency for the loop body, with the same syntax:
>
> ```js
> for await (item of itemsCursor concurrency 5) { ... }
> ```
>
> *It is important to note that this syntax does not add concurrency to the
> async iterator itself, *at least not at this time, as I believe the
> interface for defining async iterators does not currently accommodate this.
> However this syntax is still useful because it *fetches the items
> sequentially from the iterator, but may "fill the hopper" with up to five
> iterator results* that are currently being actively processed by loop
> bodies. In many cases, fetching items via an iterator is much faster than
> the processing that will be done to them in the loop bodies, and so this is
> still useful.
>
> Thanks for reading!
>
> --
> Chief Software Architect
> Apostrophe Technologies
> Pronouns: he / him / his
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to