Koa2
基于node的一个web开发框架,利用co作为底层运行框架,利用Generator的特性,实现“无回调”的异步处理;
ES7;
更小、更富有表现力、更健壮的基石;
利用async函数、Koa丢弃回调函数,增强错误处理;
很小的体积,因为没有捆绑任何中间件;
类似堆栈的方式组织和执行;
低级中间件层中提供高级“语法糖”,提高了互操性、稳健性;
Express
Node的基础框架,基础Connect中间件,自身封装了路由、视图处理等功能;
线性逻辑,路由和中间件完美融合,清晰明了;
弊端是callback回调方式,不可组合、异常不可捕获;
ES5;
connect的执行流程:
connect的中间件模型是线性的,即一个一个往下执行;
-
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 - 结束
*/