为了账号安全,请及时绑定邮箱和手机立即绑定

一个简单的es6的generator函数问题

一个简单的es6的generator函数问题

有只小跳蛙 2019-02-26 11:12:55
function* g() {var o =yield 1;    return o;}var gen = g();console.log(gen.next());console.log(gen.next());这段代码执行的时候为什么第二次返回的value是undefined,变量o的值为什么没返回?
查看完整描述

2 回答

?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

这是ES6的新feature,function 后面带 * 的叫做generator。

在generator内部你可以使用 yield 语句:


function* genFunc () {

    console.log('step 1')

    yield 1

    console.log('step 2')

    yield 2

    console.log('step 3')

    return 3

}

当你调用一个generator函数的时候,你会获得一个iterator对象。


var gen = genFunc()

这个对象有一个方法叫做 next()。每当你调用 next() 的时候,generator函数内部就会执行直到遇到下一个 yield 语句,然后暂停在那里,并返回一个对象。这个对象含有被 yield 的值和generator函数的运行状态。


var ret = gen.next() // 输出: 'step 1'

console.log(ret.value) // 1

console.log(ret.done) // false

可以看到,只输出了 'step 1'。这意味着直到你运行下一次 next() 之前,generator内部的状态处于暂停之中,但是却不影响generator外部的代码继续运行。


ret = gen.next() // 输出 'step 2'

console.log(ret.value) // 2

console.log(ret.done) // false

直到generator函数内部不再有 yield 语句存在了,这时你再调用 next(),获得的就会是该函数的常规返回值 (return 的值):


ret = gen.next() // 输出 'step 3'

console.log(ret.value) // 3

console.log(ret.done) // true

同时,iterator对象的 next() 方法是可以传递一个参数的。这个参数将会成为generator函数内对应 yield 语句的返回值:


function* genFunc () {

    var result = yield 1

    console.log(result)

}

var gen = genFunc()

gen.next() // 此时generator内部执行到 yield 1 并暂停,但还未对result赋值!

// 即使异步也可以!


setTimeout(function () {

    gen.next(123) // 给result赋值并继续执行,输出: 123

}, 1000)

虽然本意是用来提供一个可循环对象,但可以看到,generator函数可以借助 yield 在需要的时候才继续执行剩余的语句,并且传递回一个值。这让你想到了什么?没错,回调函数!更关键的是,借助generator我们可以用同步的逻辑来表达异步的流程,而不需要嵌套回调。我们只需要对创建iterator对象、调用next()以及外部函数做一些适当的封装和修改,就可以获得无回调的异步流程控制。


这个理念由TJ大神(同时也是 Koa 的作者)在 co 这个库里实现了,而 Koa 本身也是基于 co 来封装中间件函数(每一个中间件函数都是generator)。co 的实现其实不过300行代码,但是包含了很精髓的一些东西,值得细看。


**注:以下代码示例均需要 node.js v0.11.7+ 带 --harmony 参数才能运行。**


查看完整回答
反对 回复 2019-03-04
  • 2 回答
  • 0 关注
  • 437 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信