J.Krishna J.Krishna - 18 days ago 6
Javascript Question

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?

Answer

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);