Koa 和 express 区别

发布于 2024-07-18 14:18:20 字数 3592 浏览 13 评论 0

图层初始化的模式

express:采用嵌套模式,首先会创建框架中间件的 layer,也就是 app.use 和 router.use,再在中间件 layer 中创建路由的 layer,也就是 app.[httpMethods]、app.all、router.[httpMethods]、router.all。执行的顺序也就是先执行中间件 layer,再递归执行中间件中的 layer

((req, res) => {
  console.log('I am the first middleware');
  ((req, res) => {
    console.log('I am the second middleware');
    (async(req, res) => {
      console.log('I am the router middleware => /api/test1');
      await sleep(2000)
      res.status(200).send('hello')
    })(req, res)
    console.log('second middleware end calling');
  })(req, res)
  console.log('first middleware end calling')
})(req, res)

koa: 采用 promise 形式,不像 express 有两个 layer 层,koa 只有一个,用一个 middleWare 数组维护中间件,中间件执行顺序是采用洋葱模型,通过 middleMare 下标判断当前中间件是哪个,当执行 next 时,通过下标+1 递归执行 middleWare 的下一个中间件,如果出现异常则之后的中间件会被终止,直接 reject 出错误。然后再进行 handleRequest 通过 delegate 对路由事件进行委托,委托自定义的 request , responserequestresponse 又对 node 原生的 req 和 res 进行方法代理,自定义了方法。

  // middleWare 收集处理
  return function (context, next) {
    // last called middleware #
    let index = -1
    return dispatch(0)
    function dispatch (i) {
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
        return Promise.resolve(fn(context, function next () {
          return dispatch(i + 1)
        }))
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
  // 先收集 middleware,再执行路由拦截,执行方法
  callback() {
    const fn = compose(this.middleware);

    if (!this.listenerCount('error')) this.on('error', this.onerror);

    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };

    return handleRequest;
  }

koa 还会对使用了 * yield 函数进行特殊处理,也就是 koa.convert。将 generator 函数 yield 的 value 转换成 promise 方法,这样就能一直 next 下去。通过 co 函数进行转换。

function co(gen) {
  var ctx = this;
  var args = slice.call(arguments, 1);
  
  return new Promise(function(resolve, reject) {
    if (typeof gen === 'function') gen = gen.apply(ctx, args);
    if (!gen || typeof gen.next !== 'function') return resolve(gen);

    onFulfilled();
    
    function onFulfilled(res) {
      var ret;
      try {
        ret = gen.next(res);
      } catch (e) {
        return reject(e);
      }
      next(ret);
      return null;
    }

    function onRejected(err) {
      var ret;
      try {
        ret = gen.throw(err);
      } catch (e) {
        return reject(e);
      }
      next(ret);
    }

    function next(ret) {
      if (ret.done) return resolve(ret.value);
      var value = toPromise.call(ctx, ret.value);
      if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
      return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
        + 'but the following object was passed: "' + String(ret.value) + '"'));
    }
  });
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

亢潮

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文