Search code examples
javascriptkoa

how koa.js yield next works?


I have the following code in koa.js

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

app.use(function *(next) {
  console.log('A');
  yield next;
  console.log('E');
});

app.use(function *(next) {
  console.log('B');
  yield next;
  console.log('D');
});

app.use(function *(next) {
var rowCount;
  console.log('C');
  var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : 'pass',
    database : 'db1'
  });

  connection.connect();

  connection.query('SELECT * from itemcategory', function(err, rows, fields) {
    if (err) throw err;

    console.log('The solution is: ', rows);
    rowCount = rows;
    console.log('The rowCount is: ', rowCount);
  });


  this.body = "we are good!.." + rowCount ;
  connection.end();

});

app.listen(3000);

The rowCount variable prints undefined in the browser. But inside the connection.query it prints all the rows. Also the output in the console is

PS J:\proj\pg> node --harmony  .\app.js
A
B
C
D
E
The solution is:  [ { categoryno: 0, categoryname: 'PESTICIDES', categorystatus: 0 },
  { categoryno: 1, categoryname: 'SEEDS ', categorystatus: 0 },
  { categoryno: 2, categoryname: 'FERTILIZERS', categorystatus: 0 },
  { categoryno: 3, categoryname: 'OTHERS', categorystatus: 0 } ]
The rowCount is:  [ { categoryno: 0, categoryname: 'PESTICIDES', categorystatus: 0 },
  { categoryno: 1, categoryname: 'SEEDS ', categorystatus: 0 },
  { categoryno: 2, categoryname: 'FERTILIZERS', categorystatus: 0 },
  { categoryno: 3, categoryname: 'OTHERS', categorystatus: 0 } ]

As per the example in Koa it should print the rows and then only D and E, but the db rows are printed after D and E.

If the db code is removed then it prints in the correct order. I am running with harmony flag.

Please tell me what is the problem?


Solution

  • Your running the query asynchronously with a callback, which isn't the way you would want to do this in koa.

    You want to either use a library that supports promises or thunks or you can wrap the library your using so that it returns a promise or a thunk.

    Then you would yield the query, which pauses the execution of the function until a result is return, then the function continues from where it was paused with the result of the query available.

    For your example you should consider the following library:

    I haven't used it so I can't vouch for it, but it looks reasonable at a glance.

    https://github.com/sidorares/mysql-co

    This library is a wrapper over the mysql library that is yield-able.

    So your code would look like this:

    var koa = require('koa');
    var app = koa();
    var mysql = require('mysql-co');
    
    app.use(function *(next) {
      console.log('A');
      yield next;
      console.log('E');
    });
    
    app.use(function *(next) {
      console.log('B');
      yield next;
      console.log('D');
    });
    
    app.use(function *(next) {
    var rowCount;
      console.log('C');
      try{
        var connection = mysql.createConnection({
          host     : 'localhost',
          user     : 'root',
          password : 'pass',
          database : 'db1'
        });
    
        var result = yield connection.query('SELECT * from itemcategory');
        console.log(result);
    
        this.body = "we are good!.." + result.rows ;
        connection.end();
      }
      catch(err){
        // handle any errors here
      }
    });
    
    app.listen(3000);