koa訪問mysql數據庫操作

jopen 8年前發布 | 28K 次閱讀 MySQL 數據庫服務器

契機

用restify與express有一年多了,一直在考慮什么時候上koa與es6,看到 《一起學koa》 項目,決定以此為契機行動起來。首先我要完成的是對數據庫操作的封裝,將以前項目實踐中的代碼遷移到koa上來,于是決定先完成 《一起學koa》 中的mysql任務。

koa基本知識

koa依賴co,最新版基于promise實現。我們使用koa的時候都是通過use添加一個中間件,router也是一個個中間件,我們看一下use都做了什么?

app.use = function(fn){
  this.middleware.push(fn);
  return this;
};

它只是將參數保存起來,然后返回引用,最后由co完成調用,因此要求中間件中的異步調用都使用Promise形式。

實現方法一(co-mysql)

mysql庫是以回調形式實現的,而koa中間件要求Promise形式,經過搜索,發現了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
    });
...
})();

實現方法二(promisify-node)

找到promisify-node庫,可以將庫整體轉化為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
    });
...

實現方法三(thunkify、thunkify-wrap)

看tj/co說明的Yieldables部分說明如下:The yieldable objects currently supported are:

  • promises

  • thunks (functions)

  • array (parallel execution)

  • objects (parallel execution)

  • generators (delegation)

  • generator functions (delegation)

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

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

實現方法四(直接方法)

直接改造原來express下的代碼為Promise形式,參考了co-mysql,并仔細學習了Promise相關知識,完成了已有代碼的改造,代碼及說明如下: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);

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

function release(connection) {
    try {
        connection.release(function(error) {
            if (error) {
                console.log('DB-關閉數據庫連接異常!');
            }
        });
    } catch (err) {}
}
//對外接口返回Promise函數形式
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
    });
...

代碼

請參考這個項目中的數據庫操作部分,項目處于持續開發中,數據庫示例部分取自該項目。

https://github.com/zhoutk/koadmin.git

小結

koa框架以co庫為核心組織,很好的用generator來解決了回調函數問題。

來自: http://segmentfault.com/a/1190000004278608

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!