Koa
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。
正因为 Koa 没有捆绑任何中间件,所以我们在开发应用的时候一定要注意自己开发,或者找 Koa 对应的中间件,并且还要注意对应的版本。
在 Express 中我们有 express-generator ,而 Koa 官方并没有为我们提供官方的快速构建框架,但是开发者开源了非常多的优秀框架例如:
关于不同框架的使用方法不一样,在此就不一一举例,大家可以自行查阅其框架文档。Koa 主要的优势是 ES6 + 轻量定制化,以下我们就用 Koa 快速开发一个查询接口。
- 初始化项目
cd ~/Desktop && mkdir koaApp && cd koaApp
npm init
- 下载相关依赖
- koa
- koa-router
- axios
npm install koa koa-router axios --save
- 创建入口主文件 app.js
touch app.js
app.js
// 引入 koa 框架
const Koa = require('koa');
// 引入 路由
const router = require('./routes');
// 实例化应用
const app = new Koa();
// 使用路由,监听3000 端口
app
.use(router.routes())
.use(router.allowedMethods())
.listen(3000)
- 新建路由 routes/index.js
routes/index.js
const router = require('koa-router')({
prefix: '/'
})
const indexController = require('../controllers/index.js')
router.get('/', indexController.indexRender)
module.exports = router
- 创建首页控制器 controllers/index.js
controllers/index.js
const indexController = {
indexRender: async (ctx, next) => {
ctx.body = 'Hello Koa!'
}
}
module.exports = indexController;
- 启动代码,打开http://localhost:3000/,你就可以看到,Hello Koa!
nodemon app.js
第三方请求
- 新建豆瓣数据模型 models/douban.js
models/douban.js
const axios = require('axios');
const ISBNAPI = 'https://api.douban.com/v2/book/isbn/';
// const mock_id = '9787121317989';
const douban = {
isbn:function(isbn){
return new Promise((resolve,reject) => {
axios.get(ISBNAPI + isbn).then( res => {
resolve(res.data)
}).catch( err => {
reject(err.response.data)
})
})
}
}
module.exports = douban;
- 新建书目控制器 controllers/book.js
controllers/book.js
const doubanModel = require('./../models/douban');
const book = {
info:async function(ctx, next){
const ISBN = ctx.query.isbn;
if(!ISBN){
ctx.body = { code: 0,msg: 'isbn empty!'}
return
}
try{
const data = await doubanModel.isbn(ISBN);
ctx.body = { code: 200, data: data }
}catch(err) {
ctx.body = err
}
}
}
module.exports = book;
- 添加接口 routes/index.js
routes/index.js
const router = require('koa-router')({
prefix: '/'
})
const indexControllers = require('../controllers/index.js')
const bookController = require('./../controllers/book');
router.get('/', indexControllers.indexRender)
router.get('api/isbn', bookController.info);
module.exports = router
CORS中间件
Koa的机制和 Express 不一样的地方是,Express是一个流式,从上到下。而 Koa 的机制是洋葱形,中间件会有两次执行的时机。以下我们将创建全局中间件和局部的中间件,全局中间件有点类似 Express 的 filter作用,而局部中间件和 Express 的中间件相识,但是在 next 的时候需要添加 await。
- 创建输出中间件 middlewares/response.js
middlewares/response.js
const debug = require('debug')('koa-app')
/**
* 响应处理模块
*/
module.exports = async function (ctx, next) {
try {
await next()
// 处理响应结果
// 如果直接写入在 body 中,则不作处理
// 如果写在 ctx.body 为空,则使用 state 作为响应
// ctx.body = {
// code:0,
// data:{}
// }
console.log(ctx.url)
ctx.body = ctx.body ? ctx.body : {
code: ctx.state.code !== undefined ? ctx.state.code : 0,
data: ctx.state.data !== undefined ? ctx.state.data : {}
}
} catch (e) {
// catch 住全局的错误信息
debug('Catch Error: %o', e)
// 设置状态码为 200 - 服务端错误
ctx.status = 200
// 输出详细的错误信息
ctx.body = {
code: -1,
error: e && e.message ? e.message : e.toString()
}
}
}
- 创建CORS中间件 middlewares/cors.js
middlewares/cors.js
const cors = {
allowAll: async function(ctx, next){
ctx.set('Acess-Control-Allow-Origin','*');
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
ctx.set('Access-Control-Allow-Credentials', 'true');
await next()
}
}
module.exports = cors;
- 应用全局response中间件 app.js
app.js
const Koa = require('koa');
const router = require('./routes');
const app = new Koa();
const response = require('./middlewares/response');
app
.use(response)
.use(router.routes())
.use(router.allowedMethods())
.listen(3000)
- 引用CORS局部中间件 routes/index.js
routes/index.js
const router = require('koa-router')({
prefix: '/'
})
const indexControllers = require('../controllers/index.js');
const bookController = require('./../controllers/book');
const cors = require('./../middlewares/cors');
router.get('/', indexControllers.indexRender);
router.get('api/isbn', cors.allowAll,bookController.info);
module.exports = router