Handler的处理
Express普通回调函数,在同一线程上完成当前进程的所有Http请求; Koa利用Generator Function作为响应器,co作为底层运行框架,利用Generator特性,实现“协程响应”;路由
Express的路由是自身集成的; Koa的需要引入中间件Koa-router; (视图也是)启动方式
koa采用new Koa(),express采用传统的函数形式function;回调
Koa没有回调,express有回调;Http Request
koa1使用this取代Express的req、res;Context
Koa新增了一个Context对象,用来代替Express的Request和Response,作为请求的上下文对象。 还有Node原生提供的req、res、socket等对象;生命周期
Express的生命周期不确定: express内部执行异步函数,不能确定什么时候执行完; Koa的确定: koa是基于await/async,在执行下一步操作的时候,必须等待前端await执行完; const express = require('express'); const app = express(); app.use((req, res, next) => { console.log(1); // 1 next(); // 2 console.log(2); // 5 }); app.use((req, res, next) => { console.log(3); // 3 new Promise((resolve => { // 4 setTimeout(resolve, 300); })).then(() => { next(); // 6 console.log(4); // 8 }); }); app.use(function(req, res) {// 7 res.send('Hello World'); }) app.listen(3000) // 1 3 2 4 const Koa = require('koa'); const app = new Koa(); app.use(async (ctx, next) => { console.log(1); await next(); console.log(2); }); app.use(async (ctx, next) => { console.log(3); await new Promise(((resolve) => { setTimeout(resolve, 300); })); await next(); console.log(4); }); app.use(async (ctx, next) => { ctx.body = 'Hello World'; }); app.listen(3000); // 1 3 4 2异步流程
Express采用callback来处理异步(ES5); Koa1采用generator(ES6); Koa2采用async/await(ES7);错误处理
Express使用callback捕获异常,深层次的异常捕获不了; Koa使用try catch,很好的解决异常捕获;中间件
koa2的中间件: 通过async await实现的,中间件执行的顺序是“洋葱圈”模型。 中间件之间通过next函数联系,当一个中间件调用next()后,会将控制权交给下一个中间件,直到下一个中间件不再执行next()后,会沿路返回,将控制权交给前一个中间件。 const Koa = require('koa'); const app = new Koa(); // logger app.use(async (ctx, next) => { console.log('1 - 开始') await next(); const rt = ctx.response.get('X-Response-Time'); console.log('1 - 结束') }); // x-response-time app.use(async (ctx, next) => { console.log('2 - 开始') const start = Date.now(); await next(); const ms = Date.now() - start; ctx.set('X-Response-Time', `${ms}ms`); console.log('2 - 结束') }); // response app.use(async ctx => { console.log('3 - 开始') ctx.body = 'Hello World'; console.log('3 - 结束') }); app.listen(3000); /** 1 - 开始 2 - 开始 3 - 开始 3 - 结束 2 - 结束 1 - 结束 */ Express中间件: 一个接一个顺序执行,response响应写在最后一个中间件中。 特点: app.use用来注册中间件; 遇到http请求,根据path和method判断触发哪些中间件; 实现next机制,即上一个中间件会通过next触发下一个中间件; const express = require('express') const app = express() app.use((req, res, next) => { console.log('1 - 开始') setTimeout(() => { next() }, 0) console.log('1 - 结束') }) app.use((req, res, next) => { console.log('2 - 开始') setTimeout(() => { next() }, 0) console.log('2 - 结束') }) app.use('/api', (req, res, next) => { console.log('3 - 开始') res.json({ code: 0 }) console.log('3 - 结束') }) app.listen(3000, () => { console.log('server is running on port 3000') }) /** 1 - 开始 1 - 结束 2 - 开始 2 - 结束 3 - 开始 3 - 结束 */