Last active
March 28, 2021 22:09
-
-
Save noseratio/721fea7443b74a929ea93c8f6a18cec4 to your computer and use it in GitHub Desktop.
Async generators and "for await" in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// by @noseratio | |
// https://twitter.com/noseratio/status/1297517388552757249?s=20 | |
// gist: https://gist.github.com/noseratio/721fea7443b74a929ea93c8f6a18cec4/edit | |
// RunKit: https://runkit.com/noseratio/async-generators-and-for-await-in-javascript | |
async function delay(ms) { | |
await new Promise(r => setTimeout(r, ms)); | |
return ms; | |
} | |
// an array of promises to iterate through with "for await" | |
function array() { | |
return [delay(100), delay(200), delay(300)]; | |
} | |
// a synchronous generator of promises to iterate through with "for await" | |
function* generator() { | |
yield delay(100); | |
yield delay(200); | |
yield delay(300); | |
} | |
// an asynchronous generator of promises to iterate through with "for await" | |
async function* asyncGenerator() { | |
yield await delay(100); | |
yield await delay(200); | |
yield await delay(300); | |
} | |
// Simulate a "for await" loop in JavaScript, | |
// note that "await 1" is still a valid statement, | |
// which is essentially the same as "await Promise.resolve(1)" | |
async function forEachAsync(iterable, bodyFunc) { | |
const iterator = ( | |
iterable[Symbol.asyncIterator] || | |
iterable[Symbol.iterator]).call(iterable); | |
while (true) { | |
const { value, done } = await iterator.next(); | |
const awaitedValue = await value; | |
if (done) { | |
return awaitedValue; | |
} | |
await bodyFunc(awaitedValue); | |
} | |
} | |
// test with "for await" | |
async function testForAwait(iterable) { | |
let start = Date.now(); | |
for await (let value of iterable) { | |
console.log(`value: ${value}, lapse: ${Date.now() - start}`) | |
} | |
} | |
// test with "forEachAsync" | |
async function testForEach(iterable) { | |
let start = Date.now(); | |
await forEachAsync(iterable, value => { | |
console.log(`value: ${value}, lapse: ${Date.now() - start}`) | |
}) | |
} | |
// test all three sources | |
async function test(method) { | |
await delay(100); // kick the runkit runtime | |
console.log("- array") | |
await method(array()); | |
console.log("- generator") | |
await method(generator()); | |
console.log("- async generator") | |
await method(asyncGenerator()); | |
} | |
async function main() { | |
console.log("testForAwait") | |
await test(testForAwait); | |
console.log("testForEach") | |
await test(testForEach); | |
} | |
main().then(() => console.log("Finished"), e => console.log(e)); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@hvent90 the return statement L42 exits the function after going through every await message available