如何让异步生成器无数据时暂停等待,而非直接返回undefined?
解决异步生成器等待数组新元素的问题
原代码的问题在于异步生成器没有等待逻辑,当数组当前索引无元素时直接返回undefined。要实现等待新元素推入后再返回的功能,可以通过拦截数组的push方法,配合Promise实现异步等待,且不会阻塞事件循环。
修改后的代码
async function* doIt(arr) { let counter = 0; let resolveWait; // 拦截数组的push方法,新元素添加时唤醒等待的生成器 const originalPush = arr.push; arr.push = function(...items) { const result = originalPush.call(this, ...items); if (resolveWait) { resolveWait(); resolveWait = null; } return result; }; while (true) { // 当前索引无元素时,等待新元素被推入 while (counter >= arr.length) { await new Promise(resolve => { resolveWait = resolve; }); } yield arr[counter++]; } } (async() => { let arr = [1,2,3]; let x = doIt(arr); setTimeout(() => arr.push(4), 3000); console.log(await x.next()); // { value: 1, done: false } console.log(await x.next()); // { value: 2, done: false } console.log(await x.next()); // { value: 3, done: false } // 此处会等待3秒,直到4被推入后返回结果 console.log(await x.next()); // { value: 4, done: false } })()
工作原理
- 拦截
push方法:保存数组原有的push方法,重写后在每次添加新元素时,检查是否有等待中的生成器,若有则触发resolve唤醒它。 - 异步等待逻辑:当生成器发现当前索引超出数组长度时,创建一个Promise并暂停执行,直到数组被
push新元素时,Promise被resolve,生成器继续执行并yield新元素。 - 非阻塞特性:等待过程基于Promise实现,属于异步操作,不会阻塞事件循环,其他代码仍可正常运行。
内容的提问来源于stack exchange,提问作者Das Raf
相关产品推荐
相关产品推荐

