iterable & iterator are ancient concepts in programming languages. Something is iterable because it has a iterator which we can use to iterate it. Their relation and interfaces are as follows:
sync generator yield a normal value while async generator yield a promise. That’s the only difference(off course, we should add async key word before the generator function).
Another example: transforming an async iterable
1 2 3 4 5
asyncfunction* timesTwo(asyncNumbers) { forawait (const x of asyncNumbers) { yield x * 2; } }
Last real example from async-pool: throttle a bunch of requests with a max count of parallel ongoing requests:
asyncfunction* asyncPool(concurrency, iterable, iteratorFn) { const executing = newSet(); asyncfunctionconsume() { const [promise, value] = awaitPromise.race(executing); executing.delete(promise); return value; } for (const item of iterable) { // Wrap iteratorFn() in an async fn to ensure we get a promise. // Then expose such promise, so it's possible to later reference and // remove it from the executing pool. const promise = (async () => awaititeratorFn(item, iterable))().then( value => [promise, value] ); executing.add(promise); if (executing.size >= concurrency) { yieldawaitconsume(); } } while (executing.size) { yieldawaitconsume(); } }
/** * Given an array of requestsToMake and a limit on the number of max parallel requests * queue up those requests and start firing them * - inspired by Rafael Xavier's approach here: https://stackoverflow.com/a/48007240/761388 * * @paramrequestsToMake * @param maxParallelRequests the maximum number of requests to make - defaults to 6 */ asyncfunctionthrottleRequests( requestsToMake: RequestToMake[], maxParallelRequests = 6 ) { // queue up simultaneous calls constqueue: Promise<void>[] = []; for (let requestToMake of requestsToMake) { // fire the async function, add its promise to the queue, // and remove it from queue when complete const promise = requestToMake().then((res) => { queue.splice(queue.indexOf(promise), 1); return res; }); queue.push(promise);
// if the number of queued requests matches our limit then // wait for one to finish before enqueueing more if (queue.length >= maxParallelRequests) { awaitPromise.race(queue); } } // wait for the rest of the calls to finish awaitPromise.all(queue); }