Nicolas S.Xu
Nicolas S.Xu

Reputation: 14534

Why does koa use generator function as middleware without 'yield' keyword?

I had a bit experience in expressjs. Basically you implement a function with req, res, and next.

function myMidWare (req, res, next) {
   // do mid ware work

  next() // call next to trigger next middleware 
}

Later on, I see code for koa using nodejs 8.

here is a piece of code from here:

var sha1 = require('sha1');
// define a Koa middle ware
module.exports = function(opts){
    return function *(next){
        var token = opts.token;
        var signature = this.query.signature;
        var nonce = this.query.nonce;
        var timestamp = this.query.timestamp;
        var echostr = this.query.echostr;
        var str = [token,timestamp,nonce].sort().join('');
        var sha = sha1(str);
        this.body = (sha === signature) ? echostr + '' : 'failed';
    };
}

below is app.js that is using Koa middle ware defined above

// app.js - using the Koa middle ware
'use strict'

var Koa = require('koa');
var wechat = require('./wechat/generator');

var config = {
    wechat:{
        appID:'...',
        appSecret:'...',
        token:'...'
    }
};

var app = new Koa();
app.use(wechat(config.wechat));
app.listen(8080);

Then, I learned from MDN that iterator function* . function* declaration should have 'yield' key word, but I can't find 'yield' keyword in the generator function definition in above code.

Question:

  1. Why they define a generator function without 'yield' keyword?

  2. How does koa control middle ware executing sequence using generator function?

Upvotes: 0

Views: 724

Answers (1)

Jonas Wilms
Jonas Wilms

Reputation: 138267

With the new await syntax, we can stop a function execution in the middle, await something (e.g. a databse call), and then continue with the execution:

await dbcall();
await next();

In pre ES7 async code results in callback and promise hells, the only thing that supports yielding inbetween is a generator function. It creates an easy way to delegate actions and recontinue execution if they finish. A small example would be:

function asy(func){
  var gen = func();
 (function next(v){
   var res = gen.next(v);
  res.value.then(v => res.done || next(v));
 })();
}

So you can do:

asy(function* (){
  var v = yield Promise.resolve("test");
  console.log(v);
});

The whole principle is explained in depth here

So to finally answer your question: if the function does not need to yield, theres no need to yield ;)

Upvotes: 1

Related Questions