koa返回html文件_逐行分析Koa中间件机制

da5187289d20cfe43ce718ba1ee91649.png

0.背景

自从koa框架发布,已经有很多前端同行们对它的源码进行了解读。在知乎、掘金、Github上,已有不少文章讲了它的ctx等API实现、中间件机制概要、错误处理等细节,但对于中间件机制中的细节做逐行分析的文章还是比较少,本文将采用详细的逐行分析的策略,来讨论Koa中间件机制的细节。

PS:本次Koa源码分析基于2.7.0版本。

1. 从入口开始

大部分情况下使用Koa,都是这样的,假定我们的demo 入口文件叫app.js

// app.js
const Koa = require('koa');
const app = new Koa();

require在查找第三方模块时,会查找该模块下package.json文件的main字段。查看koa仓库目录下下package.json文件,可以看到模块暴露的出口是lib目录下的application.js文件

{
  "main": "lib/application.js",
}

而lib/application文件中所暴露的出口

module.exports = class Application extends Emitter {}

可以看到,在app.js 中引用koa时,变量Koa就是指向该Application类。

2.如何响应请求

(已经了解Koa如何响应请求的同学,可以跳过本节,直接看第3节)

好,现在给app.js增加一点内容:监听3004端口,打印一行日志,返回

const Koa = require('koa');
const app = new Koa();

const final = (ctx, next) => {
  console.log('Request-Start');
  ctx.body = { text: 'Hello World' };
}

app.use(final);

app.listen(3004);

// 启动app.js,就可以看到返回的结果

以上这段代码中,ctx.body 如何实现并不是本文的重点,只要知道它的作用是设置响应体的数据,就可以了

在本节里,需要搞清楚的问题有两个:

  • app.use 的作用是挂载中间件,它做了什么?
  • app.listen 的作用是监听端口,它做了哪些工作?

回到刚刚的lib/application文件,可以看到Application上挂载了use方法

use(fn) {
    // 类型判断
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');

    // 兼容v1版本的koa
    if (isGeneratorFunction(fn)) {
      deprecate('Support for generators will be removed in v3. ' +
                'See the documentation for examples of how to convert old middleware ' +
                'https://github.com/koajs/koa/blob/master/docs/migration.md');
      fn = convert(fn);
    }
    // 中间省略部分无关代码
    this.middleware.push(fn);
    return this;
  }

在官方文档里,中间件的类型是函数,因此use方法的第一行完成了参数类型的检查。

而第二段代码,则判断是否为Generator函数,如果是的话,就提示开发者Generator类型的中间件即将被废弃,并通过convert方法将该中间件的类型从Generator函数转换成普通函数。

为什么会有这么一段代码呢?因为在Koa的v1版本和v0版本,使用的异步控制方案是Generator+Promise+Co,因此将中间件定义成了Generator Function。但自从Koa v2版本起,它的异步控制方案就开始支持Async/Await,因此中间件也用普通函数就可以了。

这里用到了几个函数库,只要理解它们的作用和原理概要即可,有兴趣可以自行查看(但不看也不影响你理解后面的内容):

  • isGeneratorFunction:判断是否为Generator函数,判断方法包括Object.prototype.call、Function.prototype.call、Object.getPrototypeOf等。
  • deprecate:给出API即将被弃用的提示信息。
  • convert:即koa-convert,作用是加入了一层函数嵌套,并使用Co自动执行原Generator函数

最后一段代码的作用是把传入的函数,push到this.middleware属性的尾部,而在Application对象的构造函数里,可以看到这么一行代码

this.middleware = [];

它是用来存储中间件的。

OK,中间件通过use方法存储好了&#x

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值