I am more interested in syntax two than syntax one, which I felt should
probably be included for completeness. But hey, as you say, maybe not since
unguarded concurrency is indeed usually a mistake.

Taken on its own, do you have an objection to `for (item of items
concurrency 5) { ... }`?


On Fri, Sep 6, 2019 at 1:46 PM C. Scott Ananian <ecmascr...@cscott.net>
wrote:

> 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 <t...@apostrophecms.com> 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
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>

-- 
Chief Software Architect
Apostrophe Technologies
Pronouns: he / him / his
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to