FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
362 stars 39 forks source link

Node框架那些事儿 #254

Open FrankKai opened 2 years ago

FrankKai commented 2 years ago

nodejs框架,express,koa,egg

FrankKai commented 2 years ago

express和koa的区别

1.中间件实现方式不同 express是callback方式,会有callback hell问题;koa为洋葱模型,基于promise和async实现 2.express只有request和response对象,而koa有context对象,类似traceId,可以贯穿上下文 3.koa采用async的方式实现,所以可以以同步方式写异步逻辑,代码逻辑更加直观 4.koa异常处理更加便捷

egg和koa的区别

1.egg基于koa实现 2.egg扩展,可以扩展application,context,request,response原型对象 3.egg插件,某一类型的中间件集合,与webpack 插件类似,插拔式使用某一个功能,方便又快捷

FrankKai commented 2 years ago

koa洋葱模型中间件实现原理

const middleware = []
let mw1 = async function (ctx, next) {
    console.log("next前,第一个中间件")
    next()
    console.log("next后,第一个中间件")
}
let mw2 = async function (ctx, next) {
    console.log("next前,第二个中间件")
    next()
    console.log("next后,第二个中间件")
}
let mw3 = async function (ctx, next) {
    console.log("第三个中间件,没有next了")
}

function use(mw) {
  middleware.push(mw);
}

function compose(middleware) {
  return (ctx, next) => {
    return dispatch(0);
    function dispatch(i) {
      const fn = middleware[i];
      if (!fn) return;
      return fn(ctx, dispatch.bind(null, i+1));
    }
  }
}

use(mw1);
use(mw2);
use(mw3);

const fn = compose(middleware);

fn();

async promise版

const middleware = []
let mw1 = async function (ctx, next) {
    console.log("next前,第一个中间件")
    await next()
    console.log("next后,第一个中间件")
}
let mw2 = async function (ctx, next) {
    console.log("next前,第二个中间件")
    await next()
    console.log("next后,第二个中间件")
}
let mw3 = async function (ctx, next) {
    console.log("第三个中间件,没有next了")
}

function use(mw) {
  middleware.push(mw);
}

function compose(middleware) {
  return (ctx, next) => {
    return dispatch(0);
    function dispatch(i) {
      const fn = middleware[i];
      if (!fn) return Promise.resolve();
      return Promise.resolve(fn(ctx, dispatch.bind(null, i+1)));
    }
  }
}

use(mw1);
use(mw2);
use(mw3);

const fn = compose(middleware);

fn();
// next前,第一个中间件
// next前,第二个中间件
// 第三个中间件,没有next了
// next后,第二个中间件
// next后,第一个中间件

Koa中间件koa-compose解决了什么问题?

解决了callback回调地狱问题以及请求执行完后再执行响应的问题。 通过next()来代替下一个中间件,使得每个中间件代码封闭在各个next中。

什么时候为返回执行response的时机?

i+1不断累加,指向了middleware[middleware.length],即超出数据边界时,当fn为空时,开始执行返回逻辑。

if(!fn) return;

当前中间件执行是如何获取下一个中间件next的?

通过bind生成一个全新的middle。

dispatch.bind(null, i+1)