Skip to content

Instantly share code, notes, and snippets.

@bellbind
Created June 22, 2020 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bellbind/bf6c4f41db1a2691cd456bd4a3c36126 to your computer and use it in GitHub Desktop.
Save bellbind/bf6c4f41db1a2691cd456bd4a3c36126 to your computer and use it in GitHub Desktop.
[ECMAScript] array with async iterator
const Notifier = class {
constructor() {
this.waits = new Set();
}
get wait() {
let d = {};
const p = new Promise((f, r) => {
d.r = r; d.f = f;
});
this.waits.add(d);
return p;
}
notify() {
for (const {f} of this.waits) f();
this.waits.clear();
}
close() {
for (const {r} of this.waits) r();
this.waits.clear();
}
};
const notifiers = new WeakMap();
export const AsyncArray = class extends Array {
constructor(...args) {
super(...args);
notifiers.set(this, new Notifier());
}
push(...args) {
const r = super.push(...args);
notifiers.get(this).notify();
return r;
}
close() {
notifiers.get(this).close();
}
async *[Symbol.asyncIterator]() {
let i = 0;
try {
for (let i = 0; ; i++) {
while (i >= this.length) {
await notifiers.get(this).wait;
}
yield this[i];
}
} catch {}
}
};
import {assertEquals} from "https://deno.land/std/testing/asserts.ts";
import {AsyncArray} from "./async-array.js";
Deno.test("async array", async () => {
const a = new AsyncArray();
a.push(0);
a.push(1);
a.push(2);
(async () => {
for (let i = 3; i < 6; i++) {
await new Promise(f => setTimeout(f, 100));
a.push(i);
}
a.close();
})();
const r = [];
for await (const e of a) {
r.push(e);
}
assertEquals(r, [0,1,2,3,4,5]);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment