node.js的koa框架

一、安装部署
1.在cmd输入
npm install -g koa-generator
2.创建工作目录
koa2 HelloKoa2
进入项目输入以下命令,或者用淘宝镜像安装
cd HelloKoa2 
3.项目如果需要连接数据库,需要在package.json里dependencies添加以下内容
"mysql": "latest",
"promisify-node": "^0.3.0"
安装 或者用淘宝镜像安装
npm install
3.启动项目
npm start
二、了解koa2的中间件
1.generator中间件开发
generator 中间件在koa v2中需要用koa-convert封装一下才能使用
const Koa = require('koa'// koa v2
const convert = require('koa-convert')
const loggerGenerator  = require('./middleware/logger-generator')
const app = new Koa()

app.use(convert(loggerGenerator()))

app.use(( ctx ) => {
    ctx.body = 'hello world!'
})

app.listen(3000)
console.log('the server is starting at port 3000')
2.async 中间件开发
async 中间件只能在 koa v2中使用
const Koa = require('koa') // koa v2
const loggerAsync  = require('./middleware/logger-async')
const app = new Koa()

app.use(loggerAsync())

app.use(( ctx ) => {
    ctx.body = 'hello world!'
})

app.listen(3000)
console.log('the server is starting at port 3000')

三、连接数据库
1.创建连接数据库的文件db.js
const mysql = require('mysql')

// 创建数据池
const pool = mysql.createPool({
  host : '127.0.0.1', // 数据库地址
  user : 'root', // 数据库用户
  password : '123456', // 数据库密码
  database : 'koadmin' // 选中数据库
})

// 在数据池中进行会话操作
//执行所有的sql语句
function execQuery(sql,value,callback){
  var errinfo;
  pool.getConnection(function(err, connection) {
  if (err) {
  errinfo = 'DB-获取数据库连接异常!';
  console.log(errinfo);
  throw errinfo;
  } else {
  console.log(value);
  var querys = connection.query(sql, value, function(err, rows) {
  release(connection);
  if (err) {
  errinfo = 'DB-SQL语句执行错误:' + err;
  console.log(errinfo);
  //throw errinfo;
  callback(err);
  } else {
  callback(null,rows);
  }
  });
  console.log(querys.sql);
  }
  });
}

function release(connection) {
  try {
  connection.release(function(error) {
  if (error) {
  console.log('DB-关闭数据库连接异常!');
  }
  });
  } catch (err) {}
}

function execUpdate(sql, values, callback){
  execQuery(sql, values, function(result) {
  if (callback) {
  var affectedRows = 0;
  if (result) {
  affectedRows = result.affectedRows
  }
  callback({
  affectedRows: affectedRows
  });
  }
  });
}

//执行sql语句,返回影响条数
exports.update = function(sql, values, callback) {
  execUpdate(sql, values, callback);
}

//查询分页
exports.queryPage = function(sql, values, page, size, callback) {
  if (page > 0) {
  page--;
  } else {
  page = 0;
  }
  execQuery(sql + ' LIMIT ' + page * size + ',' + size, values, function(rresult) {
  var index = sql.toLocaleUpperCase().lastIndexOf(' FROM');
  sql = 'SELECT COUNT(*) count ' + sql.substring(index);
  execQuery(sql, values, function(cresult) {
  if (callback) {
  var pagenum = cresult[0].count / size;
  if (cresult[0].count % size > 0) {
  pagenum++;
  }
  callback({
  count: pagenum,
  rows: rresult
  });
  }
  });
  });
}

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

//查询对象
exports.getObject = function(tablename, values, callback) {
  var sql = 'SELECT * FROM ?? WHERE ?';
  execQuery(sql, [tablename, values], function(result) {
  if (callback) {
  if (result && result.length > 0) {
  callback(result[0]);
  } else {
  callback(null);
  }
  }
  });
}

//添加一条记录
exports.addObject = function(tablename, values, callback) {
  var sql = 'INSERT INTO ?? SET ?';
  execUpdate(sql, [tablename, values], callback);
}

//更新记录
exports.updateObject = function(tablename, values, id, callback) {
  var sql = 'UPDATE ?? SET ? WHERE ?';
  execUpdate(sql, [tablename,
  values, id
  ], callback);
}

//删除记录
exports.deleteObject = function(tablename, values, callback) {
  var sql = 'DELETE FROM ?? WHERE ?';
  execUpdate(sql, [tablename, values], callback);
}

2.编写routes里面的index.js
const router = require('koa-router')();
const db = require('../util/db.js');     //调用数据库
var promisify = require("promisify-node");       //调用模块

router.get('/', async (ctx, next) => {     
  await ctx.render('index', {
  })
})

router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})

router.get('/json', async (ctx, next) => {
  var rows = await db.getById('member',2);
  ctx.body = {
  rows
  }
});

module.exports = router

问题:因为对es6语法不了解,在async函数中没有家await,因此一直导致rows为空
在index.js中,你要知道async和await的写法和用途
我们要了解以下几个概念。
1)Promise对象
Promise对象是为了解决多个回调函数嵌套。
fs.readFile(fileA, 'utf-8', function (err, data) {
  fs.readFile(fileB, 'utf-8', function (err, data) {
  // ...
  });
});
var readFile = require('fs-readfile-promise');

readFile(fileA)
.then(function (data) {
  console.log(data.toString());
})
.then(function () {
  return readFile(fileB);
})
.then(function (data) {
  console.log(data.toString());
})
.catch(function (err) {
  console.log(err);
});
解决方法如上
2)Generator函数
协成

传统的编程语言,早有异步编程的解决方案(其实是多任务的解决方案)。其中有一种叫做"协程"(coroutine),意思是多个线程互相协作,完成异步任务。

协程有点像函数,又有点像线程。它的运行流程大致如下。

  • 第一步,协程A开始执行。
  • 第二步,协程A执行到一半,进入暂停,执行权转移到协程B
  • 第三步,(一段时间后)协程B交还执行权。
  • 第四步,协程A恢复执行。

上面流程的协程A,就是异步任务,因为它分成两段(或多段)执行。

function *asyncJob() {
  // ...其他代码
  var f = yield readFile(fileA);
  // ...其他代码
}

上面代码的函数 asyncJob是一个协程,它的奥妙就在其中的 yield命令。它表示执行到此处,执行权将交给其他协程。也就是说, yield命令是异步两个阶段的分界线。

协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。它的最大优点,就是代码的写法非常像同步操作,如果去除yield命令,简直一模一样。

3)async函数
async 函数就是将 Generator 函数的星号( * )替换成 async ,将 yield 替换成 await
var gen = function* () {
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};
var asyncReadFile = async function () {
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};
async await ,比起星号和 yield ,语义更清楚了。 async 表示函数里有异步操作, await 表示紧跟在后面的表达式需要等待结果。

async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值