仿koa2 compose,实现自己的中间件

临时接到任务,要写中间件,然后就仿照了两篇博客,这两篇博客会在最后给出。

app.js

class App {
  constructor() {
    this.middlewares = [];
  }
  use(fn) {
    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!');
    this.middlewares.push(fn);
  }
  compose() {
    const self = this;
    return function (ctx, next) {
      // last called middleware #
      let index = -1
      function dispatch(i) {
        if (i <= index) return Promise.reject(new Error('next() called multiple times'))
        index = i
        let fn = self.middlewares[i];
        // 检测中间件有效性,为空时结束return Promise直接resolve
        // 此时流程就会往回执行
        if (i === self.middlewares.length) fn = next
        if (!fn) return Promise.resolve()
        // 中间件有效,resolve一个function回溯调用关键
        try {
          return Promise.resolve(fn(ctx, function next() {
            // next()执行下一中间件
            return dispatch(i + 1)
          }))
        } catch (err) {
          return Promise.reject(err)
        }
      }
      return dispatch(0)
    }
  }
  // 创建全局上下文
  createContext() {
    const ctx = {
      message: 'hello'
    }
    return ctx;
  }
  // 处理器
  handles(ctx, fn) {
    return fn(ctx);
  }
  callback() {
    const fn = this.compose();
    const ctx = this.createContext();
    this.handles(ctx, fn);
  }
}
module.exports = App;

使用demo测试

test.js

const App = require("./app2");
const app = new App();
// 异步函数
function fn() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello');
    }, 500);
  });
}
function foo(a, b) {
  return a * b
}
app.use(async (ctx, next) => {
  ctx.a = '123';
  console.log(foo(1, 1));
  await next();
  console.log(2);
});
app.use(async (ctx, next) => {
  console.log(3,ctx.a,ctx.message);
  console.log('fn', await fn())// 调用异步函数
  await next();
  console.log(4);
});
app.use(async (ctx, next) => {
  console.log(5);
  await next();
  console.log(6);
});

app.callback();

参考链接:

  1. KOA2 compose 串联中间件实现(洋葱模型)
  2. koa2中间件koa和koa-compose源码分析原理(一)

你可能感兴趣的:(node)