ずいぶん前に、Repeaterっていう抽象化を書いたんだ。要するに、Promiseコンストラクタが非同期イテラブルに翻訳されたらどうなるかっていうアイデア。import { Repeater } from "@repeaterjs/repeater"; const keys = new Repeater(async (push, stop) => { const listener = (ev) => { if (ev.key === "Escape") { stop(); } else { push(ev.key); } }; window.addEventListener("keyup", listener); await stop; window.removeEventListener("keyup", listener); }); const konami = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a"]; (async function() { let i = 0; for await (const key of keys) { if (key === konami[i]) { i++; } else { i = 0; } if (i >= konami.length) { console.log("KONAMI!!!"); break; // keyupリスナーを削除 } } })(); https://github.com/repeaterjs/repeater これは機能が完全で安定してる抽象化の一つで、NPMを見てみると、何らかの理由で週に650万回以上ダウンロードされてるみたい。最近は、著者とは逆の見解を持っていて、特にfetch提案にどれだけ埋め込まれているかを考えると、ストリームを使うべきだと思ってる。でも、teeの批判は致命的だから、もしかしたら著者が正しいのかも。まだこのことについて考えている人がいるのはワクワクするね。非同期イテラブルをデフォルトの抽象化にするのがいいと思う。