Express 是一个自身功能极简,彻底是由路由和中间件构成一个的 web 开发框架:从本质上来讲,一个 Express 应用就是在调用各类中间件。javascript
中间件(Middleware) 是一个函数,它能够访问请求对象(request object (req
)), 响应对象(response object (res
)), 和 web 应用中处于请求-响应循环流程中的中间件,通常被命名为 next
的变量。html
若是当前中间件没有终结请求-响应循环,则必须调用 next()
方法将控制权交给下一个中间件,不然请求就会挂起。java
Koa目前主要分1.x版本和2.x版本,它们最主要的差别就在于中间件的写法,git
redux的middleware是提供的是位于 action 被发起以后,到达 reducer 以前的扩展点。github
框架 | 异步方式 |
---|---|
Express | callback |
Koa1 | generator/yield+co |
Koa2 | Async/Await |
Redux | redux-thunk,redux-saga,redux-promise等 |
//Express
var express = require('express')
var app = express()
app.get('/',(req,res)=>{
res.send('Hello Express!')
})
app.listen(3000)
复制代码
var koa = require('koa');
var app = koa();
// logger
app.use(function *(next){
var start = new Date;
yield next;
var ms = new Date - start;
console.log('%s %s - %s', this.method, this.url, ms);
});
// response
app.use(function *(){
this.body = 'Hello World';
});
app.listen(3000);
复制代码
const Koa = require('koa');
const app = new Koa();
// logger
// common function 最多见的,也称modern middleware
app.use((ctx, next) => {
const start = new Date();
return next().then(() => {
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
});
// logger
// generatorFunction 生成器函数,就是yield *那个
app.use(co.wrap(function *(ctx, next) {
const start = new Date();
yield next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}));
// logger
// async function 最潮的es7 stage-3特性 async 函数,异步终极大杀器
app.use(async (ctx, next) => {
const start = new Date();
await next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
// response
app.use(ctx => {
ctx.body = 'Hello Koa';
});
app.listen(3000);
复制代码
import { createStore, applyMiddleware } from 'redux'
/** 定义初始 state**/
const initState = {
score : 0.5
}
/** 定义 reducer**/
const reducer = (state, action) => {
switch (action.type) {
case 'CHANGE_SCORE':
return { ...state, score:action.score }
default:
break
}
}
/** 定义中间件 **/
const logger = ({ dispatch, getState }) => next => action => {
console.log('【logger】即将执行:', action)
// 调用 middleware 链中下一个 middleware 的 dispatch。
let returnValue = next(action)
console.log('【logger】执行完成后 state:', getState())
return returnValue
}
/** 建立 store**/
let store = createStore(reducer, initState, applyMiddleware(logger))
/** 如今尝试发送一个 action**/
store.dispatch({
type: 'CHANGE_SCORE',
score: 0.8
})
/** 打印:**/
// 【logger】即将执行: { type: 'CHANGE_SCORE', score: 0.8 }
// 【logger】执行完成后 state: { score: 0.8 }
复制代码
其实express middleware的原理很简单,express内部维护一个函数数组,这个函数数组表示在发出响应以前要执行的全部函数,也就是中间件数组,每一次use之后,传进来的中间件就会推入到数组中,执行完毕后调用next方法执行函数的下一个函数,若是没用调用,调用就会终止。web
Koa会把多个中间件推入栈中,与express不一样,koa的中间件是所谓的洋葱型模型。express
var koa = require('koa');
var app = koa();
app.use(function*(next) {
console.log('begin middleware 1');
yield next;
console.log('end middleware 1');
});
app.use(function*(next) {
console.log('begin middleware 2');
yield next;
console.log('end middleware 2');
});
app.use(function*() {
console.log('middleware 3');
});
app.listen(3000);
// 输出
begin middleware 1
begin middleware 2
middleware 3
end middleware 2
end middleware 1
复制代码
从上图中得出结论,middleware经过next(action)一层层处理和传递action直到redux原生的dispatch。而若是某个middleware使用store.dispatch(action)来分发action,就至关于从新来一遍。redux
在middleware中使用dispatch的场景通常是接受一个定向action,这个action并不但愿到达原生的分发action,每每用在一步请求的需求里,如redux-thunk,就是直接接受dispatch。api
若是一直简单粗暴调用store.dispatch(action),就会造成无限循环。数组