JavaScript异步生成器中"yield await"是否属于冗余写法?
异步生成器中
yield somePromise与yield await somePromise的行为差异分析 核心结论
大部分场景下两者行为一致,但存在细微但关键的例外场景,yield await并非完全冗余。
一、常规场景的一致性
异步生成器(async function*)在迭代时,会自动等待yield出去的Promise完成,再将结果作为迭代器的value返回。因此不管是直接yield Promise,还是先await获取Promise结果再yield,最终传递给调用者的迭代结果完全相同。
示例代码:
async function* genDirect() { yield Promise.resolve('test value'); } async function* genAwait() { yield await Promise.resolve('test value'); } // 调用后输出结果一致 (async () => { for await (const val of genDirect()) console.log(val); // 输出 test value for await (const val of genAwait()) console.log(val); // 输出 test value })();
二、需要注意的例外场景
1. Promise拒绝时的错误捕获时机
当yield的Promise被拒绝时,两者的错误传播路径完全不同:
- 直接
yield someRejectedPromise:错误会延迟到迭代器被消费(for await...of或next()调用)时抛出,只能被调用方的try/catch捕获,生成器内部的try/catch无法拦截; yield await someRejectedPromise:await会将Promise的拒绝转化为生成器内部的同步错误,可被生成器自身的try/catch捕获,不会直接传递到调用方。
示例代码:
async function* genYieldReject() { try { yield Promise.reject(new Error('内部无法捕获')); } catch (e) { console.log('生成器内部捕获:', e.message); // 此代码不会执行 } } async function* genYieldAwaitReject() { try { yield await Promise.reject(new Error('内部可以捕获')); } catch (e) { console.log('生成器内部捕获:', e.message); // 输出 生成器内部捕获: 内部可以捕获 } } (async () => { // 测试第一个生成器 try { for await (const val of genYieldReject()) {} } catch (e) { console.log('外部捕获:', e.message); // 输出 外部捕获: 内部无法捕获 } // 测试第二个生成器 for await (const val of genYieldAwaitReject()) {} // 无外部错误抛出 })();
2. 链式Promise调用的处理逻辑
如果yield的是Promise链式调用的中间结果,await会改变执行顺序和错误处理范围:
async function* genChainYield() { yield Promise.resolve(1).then(() => Promise.reject('链式错误')); } async function* genChainAwait() { try { yield await Promise.resolve(1).then(() => Promise.reject('链式错误')); } catch (e) { console.log('内部捕获链式错误:', e); // 输出 内部捕获链式错误: 链式错误 } }
genChainYield中,yield的是链式调用返回的拒绝Promise,错误只能被外部捕获;genChainAwait中,await会等待整个链式调用完成,错误在生成器内部被拦截处理。
三、使用建议
- 若仅需将Promise的最终结果传递给调用方,无需在生成器内部处理错误,
yield somePromise足够,yield await属于冗余写法; - 若需要在生成器内部捕获Promise错误、或确保Promise状态处理完成后再执行后续逻辑,必须使用
yield await。
内容的提问来源于stack exchange,提问作者jmartinezmaes
相关产品推荐
相关产品推荐

