Home  >  Q&A  >  body text

javascript - node.js 中 function *(next){} 用法?

koajs readme里的示例代码,地址 https://github.com/koajs/koa
其中像app.use(function *(next){})*的作用是什么?这样写有什么好处?

var koa = require('koa');
var app = koa();

// logger

app.use(function *(next){
  var start = new Date;
  yield next;
  var ms = new Date - start;
  console.log('%s %s - %s', this.method, this.url, ms);
});

// response

app.use(function *(){
  this.body = 'Hello World';
});

app.listen(3000);
迷茫迷茫2749 days ago524

reply all(5)I'll reply

  • PHPz

    PHPz2017-04-10 14:44:20

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

    这是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行代码,但是包含了很精髓的一些东西,值得细看。

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 14:44:20

    这个是 Ecma Script Harmony (ES6)带来的新语法。

    关于详细的,可以参考这个大大的 PPT

    http://vdisk.weibo.com/s/544GFEuUPkI

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 14:44:20

    可以参考这个
    http://es6.ruanyifeng.com/#docs/generator

    reply
    0
  • 黄舟

    黄舟2017-04-10 14:44:20

    http://stackoverflow.com/questions/9620586/function-in-javascript

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 14:44:20

    生成器是一个大特性未来应该会有大应用: https://www.imququ.com/post/generator-function-in-es6.html

    reply
    0
  • Cancelreply