美文网首页
koa 洋葱模型

koa 洋葱模型

作者: 隔壁老王的隔壁啊 | 来源:发表于2019-05-24 23:02 被阅读0次

分析

1、首先这是koa2最简单的入门例子,我将通过这个入门例子来演示koa2的洋葱模型

const Koa = require('koa');
const app = new Koa();
app.use((ctx,next)=>{
    console.log("第一个中间件执行");    
   next() ;
});

// 第二个中间件
app.use((ctx,next)=>{
    console.log("第二个中间件");
})

let r = app.listen(8080);
console.log("server run on 8080");

在这里面,app首先是调用了两次use,然后就开始监听端口,

listen(...args) {
    debug('listen');
    // 当客户端发送请求将会调用callback
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }

因此use是核心:

 use(fn) {
    // ... 一些判断代码
    this.middleware.push(fn);
    return this;
  }

从上面可以看出这里将外部use的函数通过内部的一个middleware变量记录下来,然后就没了。

OK,现在当客户端发送请求的时候,内部会创建上下文对象,然后处理请求:

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;
  }

处理请求

handleRequest(ctx, fnMiddleware) {
    const res = ctx.res;
    res.statusCode = 404;
    const onerror = err => ctx.onerror(err);
    const handleResponse = () => respond(ctx);
    onFinished(res, onerror);
    // 核心,调用中间件,从这里可以看出我们use(fn)中的fn是一个promise
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
  }

OK,到这里我们知道当浏览器发送一个请求的时候,koa的application对象会根据middleware调用compose来生成一个另一个函数fn,然后向fn中传入上下文ctx执行这个函数。我们都知道,最上面的代码执行顺序是先打印第一个中间件执行,再打印第二个中间件执行,那么这个compose这个函数就需要来保证这个机制。具体怎么实现看如下:

function compose (middleware) {
  if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
  for (const fn of middleware) {
    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
  }

  /**
   * @param {Object} context
   * @return {Promise}
   * @api public
   */

  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, dispatch.bind(null, i + 1)));
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
}

上面代码虽然不多,但是是koa2实现洋葱模型最重要的部分。整个过程如下:

  1. 客户端发送请求,调用fn(ctx),此时next为空=>dispatcher(0),获取第一次use的函数(middleware[0])执行这个函数,参数为:ctx、dispatch(1),这个dispatcher(1),也就是第一次use中的next;执行next();
  2. 在第一次use中的方法体中执行next()等价于执行dispatcher(1),此时获取第二次use的函数(middleware[1]),接着再执行这个函数,参数为:ctx、dispatch(2),以此类推执行后面的中间件.

总结

koa2源码虽然少,但是原理巧妙,值得学习,也正是因为它的小,对于w我们看源码学习也能更轻松.

相关文章

  • 【Node】深入浅出 Koa 的洋葱模型

    本文将讲解 koa 的洋葱模型,我们为什么要使用洋葱模型,以及它的原理实现。掌握洋葱模型对于理解 koa 至关重要...

  • koa洋葱模型

    koa-compose:koa-compose则是将 koa/koa-router 各个中间件合并执行,结合 ne...

  • koa洋葱模型

    前几天面试node,面试官问了koa的中间件是如何实现的,我一想,卧槽,这特么不是我很熟悉的么,然后就哇啦啦啦的一...

  • koa 洋葱模型

    分析 1、首先这是koa2最简单的入门例子,我将通过这个入门例子来演示koa2的洋葱模型 在这里面,app首先是调...

  • 【源码学习----koa】koa中间件核心(koa-compos

    最近经常使用koa进行服务端开发,迷恋上了koa的洋葱模型,觉得这玩意太好用了。而且koa是以精简为主,没有很多集...

  • koa 中间件机制以及异常捕获

    koa 中间件机制以及异常捕获 koa 中间件机制解析 koa 的请求处理是典型的洋葱模型,下面是官方的配图,而这...

  • koa洋葱模型原理

    首先,关于 洋葱模型 自上而下-》自下而上 回溯机制并不是 koa 自己的特性,而是 async/await 自己...

  • koa全攻略

    1.什么是洋葱模型 简单介绍 用一句话来说,koa,express框架的中间件的执行顺序,可以比喻成洋葱模型。 我...

  • jk node笔记(2)

    express 中间件在没有异步的情况下,符合洋葱模型,一旦有了异步,就会打破洋葱模型。koa 中使用异步函数写中...

  • koa

    koa的处理流程 koa的中间件 洋葱模型实现 通过await next();进入下一个中间件 next是comp...

网友评论

      本文标题:koa 洋葱模型

      本文链接:https://www.haomeiwen.com/subject/exeozqtx.html