JavaScript生成器执行流程疑问:为何最后再次输出before yield?
为什么JavaScript生成器最后会再次执行
before yield的日志? 我写了一段JavaScript生成器测试代码:
function* listener() { console.log('listening'); while (true) { console.log('before yield'); /** Why this is getting print in end again**/ let msg = yield; console.log('after yield', msg); } } let l = listener(); l.next('are you there?'); console.log('-----'); l.next('how are you?');
运行输出为:
listening before yield ----- after yield how are you? before yield
整体输出看似正常,但我不理解为何代码流程最后会再次回到console.log('before yield')并执行输出,希望有人帮忙讲解这一概念。
解答
把生成器的执行步骤拆解开,就能明白这个现象:
第一次调用
l.next('are you there?'):- 调用
listener()只是创建生成器对象,不会立即执行函数体,第一次next()才会启动执行。 - 函数先打印
listening,进入while(true)循环后打印before yield。 - 遇到
yield语句时生成器暂停执行,停在let msg = yield;这一行(还没给msg赋值)。另外,第一次next()传入的参数会被忽略——这个参数是用来传递给上一次yield的返回值,但此时还没有上一次的yield。
- 调用
执行
console.log('-----'):- 这是普通同步日志打印,和生成器执行无关。
第二次调用
l.next('how are you?'):- 生成器从上次暂停的
yield处恢复,把传入的'how are you?'赋值给msg。 - 执行
console.log('after yield', msg),打印出after yield how are you?。 - 循环继续,回到
while(true)开头,再次执行console.log('before yield'),随后又碰到yield语句,生成器再次暂停——这就是最后那条before yield的来源。
- 生成器从上次暂停的
简单说,每次调用next()恢复生成器后,代码会一直执行到下一个yield才暂停。第二次next()跑完after yield的日志后,循环回到开头执行before yield,然后再次因yield暂停,所以这条日志出现在了输出末尾。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

