一、安装部署
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
命令的语法糖。