前言
Koa中间件机制:Koa中间件机制就是函数式组合概念 Compose的概念,将一组需要顺序执行的 函数复合为一个函数,外层函数的参数实际是内层函数的返回值。
下面我们看一下一个基本函数组合是怎么实现的
两个函数组合
const add = (x, y) => x + y
const square = z => z * z
const fn = (x, y) => square(add(x, y))
console.log(fn(1, 2)) // 9
上面的函数中,add的返回值又传给了square,这样,就组成了一个新的函数,增强了函数的功能,这就是函数组合的基本作用。
现在我们把它组合成一个函数
const compose = (fn1, fn2) => (...args) => fn2(fn1(...args))
const fn = compose(add,square)
fn(1, 2) // 9
我们用compose把两个函数组合成了一个函数。那如果是个多个函数组合成一个函数怎么做呢?
多个函数组合
我们可以用数组模拟的方式实现多个函数的组合
const add = (x, y) => x + y
const square = z => z * z
const compose = (...[first, ...other]) => (...args) => {
let ret = first(...args);
other.forEach(fn => {
ret = fn(ret)
})
return ret
}
const fn = compose(add, square)
fn(1, 2) // 9
异步中间件
上面的函数都是同步的,挨个遍历执行即可,如果是异步的函数呢,是一个 promise,我们要支持async + await的中间件,所以我们要等异步结束后,再执行下一个中间 件。
function compose(middlewares) {
return function() {
return dispatch(0);
// 执行第0个
function dispatch(i) {
let fn = middlewares[i];
if (!fn) {
return Promise.resolve();
}
return Promise.resolve(
fn(function next() {
// promise完成后,再执行下一个
return dispatch(i + 1);
})
);
}
};
}
async function fn1(next) {
console.log("fn1");
await next();
console.log("end fn1");
}
async function fn2(next) {
console.log("fn2");
await delay();
await next();
console.log("end fn2");
}
function fn3(next) {
console.log("fn3");
}
function delay() {
return new Promise((reslove, reject) => {
setTimeout(() => {
reslove();
}, 2000);
});
}
const middlewares = [fn1, fn2, fn3];
const finalFn = compose(middlewares);
finalFn();
输出结果:
fn1
fn2
fn3
end fn2
end fn1