亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Node.js的Koa框架上手及MySQL操作指南

 更新時間:2016年06月13日 17:45:34   作者:zhoutk  
Node世界中新興的Koa框架比Express更加輕便,且擴(kuò)展對數(shù)據(jù)庫操作的支持十分強(qiáng)大,這里我們就來看一下Node.js的Koa框架上手及MySQL操作指南:

由 Express 原班人馬打造的 koa,致力于成為一個更小、更健壯、更富有表現(xiàn)力的 Web 框架。使用 koa 編寫 web 應(yīng)用,通過組合不同的 generator,可以免除重復(fù)繁瑣的回調(diào)函數(shù)嵌套,并極大地提升常用錯誤處理效率。Koa 不在內(nèi)核方法中綁定任何中間件,它僅僅提供了一個輕量優(yōu)雅的函數(shù)庫,使得編寫 Web 應(yīng)用變得得心應(yīng)手。

安裝koa
koa 依賴支持 generator 的 Node 環(huán)境,也就是說,node的版本要在 0.11.9 或者更高,否則將無法執(zhí)行。

用npm:

$ npm install koa

或者,選擇安裝在全局:

$ npm install -g koa

Example
這是一個koa的簡單例子:

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

與普通的 function 不同,generator functions 以 function* 聲明。以這種關(guān)鍵詞聲明的函數(shù)支持 yield。在后面會講到 yield 的用法和意義。

執(zhí)行koa
執(zhí)行koa時需要在 —-harmony 模式下運行,為了方便可以將 node 設(shè)置為默認(rèn)啟動 harmony 模式的別名:

alias node='node --harmony'

這樣在執(zhí)行相關(guān)js的時候就可以直接使用了。

Cascading
這是一個比較抽象的概念。Koa 中間件以一種非常傳統(tǒng)的方式級聯(lián)起來,也就是這里所謂的Cascading。

在以往的 Node 開發(fā)中,頻繁使用回調(diào)不太便于展示復(fù)雜的代碼邏輯,在 Koa 中,我們可以寫出真正具有表現(xiàn)力的中間件。與 Connect 實現(xiàn)中間件的方法相對比,Koa 的做法不是簡單的將控制權(quán)依次移交給一個又一個的中間件直到程序結(jié)束,Koa 執(zhí)行代碼的方式有點像回形針,用戶請求通過中間件,遇到 yield next 關(guān)鍵字時,會被傳遞到下一個符合請求的路由(downstream),在 yield next 捕獲不到下一個中間件時,逆序返回繼續(xù)執(zhí)行代碼(upstream)。

下邊這個例子展現(xiàn)了使用這一特殊方法書寫的 Hello World 范例:一開始,用戶的請求通過 x-response-time 中間件和 logging 中間件,這兩個中間件記錄了一些請求細(xì)節(jié),然后「穿過」 response 中間件一次,最終結(jié)束請求,返回 「Hello World」。

當(dāng)程序運行到 yield next 時,代碼流會暫停執(zhí)行這個中間件的剩余代碼,轉(zhuǎn)而切換到下一個被定義的中間件執(zhí)行代碼,這樣切換控制權(quán)的方式,被稱為 downstream,當(dāng)沒有下一個中間件執(zhí)行 downstream 的時候,代碼將會逆序執(zhí)行。

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

// x-response-time
app.use(function *(next){
 // (1) 進(jìn)入路由
 var start = new Date;
 yield next;
 // (5) 再次進(jìn)入 x-response-time 中間件,記錄2次通過此中間件「穿越」的時間
 var ms = new Date - start;
 this.set('X-Response-Time', ms + 'ms');
 // (6) 返回 this.body
});

// logger
app.use(function *(next){
 // (2) 進(jìn)入 logger 中間件
 var start = new Date;
 yield next;
 // (4) 再次進(jìn)入 logger 中間件,記錄2次通過此中間件「穿越」的時間
 var ms = new Date - start;
 console.log('%s %s - %s', this.method, this.url, ms);
});

// response
app.use(function *(){
 // (3) 進(jìn)入 response 中間件,沒有捕獲到下一個符合條件的中間件,傳遞到 upstream
 this.body = 'Hello World';
});

app.listen(3000);

在上方的范例代碼中,中間件以此被執(zhí)行的順序已經(jīng)在注釋中標(biāo)記出來。你也可以自己嘗試運行一下這個范例,并打印記錄下各個環(huán)節(jié)的輸出與耗時。

.middleware1 {
 // (1) do some stuff
 .middleware2 {
  // (2) do some other stuff
  .middleware3 {
   // (3) NO next yield !
   // this.body = 'hello world'
  }
  // (4) do some other stuff later
 }
 // (5) do some stuff lastest and return
}

上方的偽代碼中標(biāo)注了中間件的執(zhí)行順序,看起來是不是有點像 ruby 執(zhí)行代碼塊(block)時 yield 的表現(xiàn)了?也許這能幫助你更好的理解 koa 運作的方式。

koa訪問mysql數(shù)據(jù)庫操作
實現(xiàn)方法一(co-mysql)
mysql庫是以回調(diào)形式實現(xiàn)的,而koa中間件要求Promise形式,經(jīng)過搜索,發(fā)現(xiàn)了co-mysql和mysql-co,這兩個庫的思路差不多,mysql-co封裝度更高,并使用速度更快的mysql2,而co-mysql更簡單,只是將mysql.query封裝成Promise形式。下面是基于co-mysql的寫法

var wrapper = require('co-mysql'),
 mysql = require('mysql');
var options = {
  host : 'localhost',
  port : 3306 ,
  database : 'test',
  user: 'root',
  password : 'rootroot'
};

var pool = mysql.createPool(options),
 p = wrapper(pool);

...
 var rows = yield p.query('SELECT 1');
 yield this.render('index', {
    title: rows[0].fieldName
  });
...
})();

實現(xiàn)方法二(promisify-node)
找到promisify-node庫,可以將庫整體轉(zhuǎn)化為Promise形式,示例代碼如下:

var promisify = require("promisify-node");
var db = promisify("myDbHelper");
...
var rows = yield db.getById('tableName', {id:1});
  yield this.render('index', {
    title: rows[0].fieldName
  });
...

實現(xiàn)方法三(thunkify、thunkify-wrap)

使用thunkify也能夠完成封裝,thunkify-wrap是一個增強(qiáng)版的thunkify,不過看說明,這種方法在未來的發(fā)展中可能會被淘汰,大概的使用如下:

var genify = require('thunkify-wrap').genify;
var db = genify("myDbHelper");
...
var rows = yield db.getById('tableName', {id:1});
  yield this.render('index', {
    title: rows[0].fieldName
  });
...

實現(xiàn)方法四(直接方法)
直接改造原來express下的代碼為Promise形式,參考了co-mysql,并仔細(xì)學(xué)習(xí)了Promise相關(guān)知識,完成了已有代碼的改造,代碼及說明如下:
dbHelper.js

var config = require('./dbconfig');

var options = {
  'host': config.db_host,
  'port': config.db_port,
  'database': config.db_name,
  'user': config.db_user,
  'password': config.db_passwd
}

var mysql = require('mysql');
var pool = mysql.createPool(options);

//內(nèi)部對mysql的封裝,執(zhí)行sql語句
function execQuery(sql, values, callback) {
  var errinfo;
  pool.getConnection(function(err, connection) {
    if (err) {
      errinfo = 'DB-獲取數(shù)據(jù)庫連接異常!';
      throw errinfo;
    } else {
      var querys = connection.query(sql, values, function(err, rows) {
        release(connection);
        if (err) {
          errinfo = 'DB-SQL語句執(zhí)行錯誤:' + err;
          callback(err);
        } else {
          callback(null,rows);    //注意:第一個參數(shù)必須為null
        }
      });
    }
  });
}

function release(connection) {
  try {
    connection.release(function(error) {
      if (error) {
        console.log('DB-關(guān)閉數(shù)據(jù)庫連接異常!');
      }
    });
  } catch (err) {}
}
//對外接口返回Promise函數(shù)形式
exports.getById = function(tablename, id){
  return new Promise(function(resolve, reject){
    var values = {id:id};
    var sql = 'select * from ?? where ?';
    execQuery(sql,[tablename, values], function(err, rows){
      if(err){
        reject(err);
      }else{
        resolve(rows);
      }
    })
  });
}
routes/index.js

var db = require("../dbHelper");
...
var rows = yield db.getById('tableName', {id:1});
  yield this.render('index', {
    title: rows[0].fieldName
  });
...

代碼
請參考這個項目中的數(shù)據(jù)庫操作部分,項目處于持續(xù)開發(fā)中,數(shù)據(jù)庫示例部分取自該項目。
https://github.com/zhoutk/koadmin.git

相關(guān)文章

最新評論