文章已同步至掘金:https://juejin.cn/post/6844903922428035085
欢迎访问😃,有任何问题都可留言评论哦~
提到 Node 就不得不说其中的两大框架Express
和Koa
然而这两者之间又有什么 渊源 和 爱恨情仇 呢?
说到Express
和Koa
,我们都会发现,他们都会有 中间件(middlewares) 的概念
什么是中间件?
中间件(middlewares)其实就是一个函数
它可以访问请求对象(request object(req))
, 响应对象(response object(res))
, 和 web 应用
中处于请求-响应循环流程中的中间件。
例子:
比如:生活中的租客和房主,中间需要一个中介来搭桥,这个中介就类似于中间件。
在说下面的例子时,会涉及到中间件的解释
Express
与Koa
的区别
中间件的执行顺序:
其实在两种框架中,中间件的执行顺序都是自上而下的
然而最大的区别就是:
Express
中间件链是基于回调的Koa
是基于 Promise 的
模型:
Express
为 线性模型
Koa
为 洋葱型模型
功能:
Express
包含了一个完整的应用程序框架,具有路由、模板等功能。
Koa
的核心模块只是 中间件内核,但是Koa
却有这些功能的选项,但他们是单独的模块,用的时候需要 npm 安装
所以,Koa
的模块化程度更高,因此,如果你只需要核心请求应答上下文对象,则Koa
占用空间非常小。相比较而言,Express
较为庞大,内置了一整套中间件功能,好处是对于大部分应用场合你可以省掉自己选择和组合模块的时间。
Express
中间件执行是有顺序的
输出结果:
从上述代码,可以看到,启动服务后当你访问 127.0.0.1:3000/ 的时候,就会打印出相应的内容,所以Express
是线性的
再给一个例子:
根据这个例子就可以知道,其中具有 路由 功能,包括 get
、post
…
再看下面这个例子:
输出结果:
但是如果没有内部的异步处理,直接调用next()
呢?
输出结果:
其实这种输出结果是由于代码的同步导致的,和洋葱模型不一样
当中间件内没有异步操作时,其实代码是以这种方式运行的:
输出结果:
可以看到就是一层一层嵌套的回调,就是很简单的回调函数,所以代码还是要一步一步的往下走的
所以说Express
的中间件是线性的,next
过后继续寻找下一个中间件
Express
错误处理:
输出内容:
源码解析
这里只说部分核心代码(参考别的文章的)
这里看不懂就算了,完全不用看
中间件的挂载主要依赖 proto.use
和 proto.handle
,(删除部分 if 判断)
proto.use
主要将我们需要挂载的中间件存储在其自身 stack
属性上,同时进行部分兼容处理,这一块比较容易理解。其中间件机制的核心为 proto.handle
内部 next
方法的实现。
在删除掉部分非核心代码后,可以清晰的看到,proto.handle
的核心就是 next
方法的实现和递归调用,对存在于 stack
中的中间件取出、执行。
这里便可以解释上文中异步和非异步过程中所输出的结果的差异:
- 当有异步代码时,将会直接跳过继续执行,此时的
next
方法并未执行,需要等待当前队列中的事件全部执行完毕,所以此时我们输出的数据是线性的。 - 当
next
方法直接执行时,本质上所有的代码都已经为同步,所以层层嵌套,最外层的肯定会在最后,输出了类似剥洋葱模型的结果。
Koa
相比较 Express
而言,Koa
的整体设计和代码实现显得更高级,更精炼 因为在Koa
中,只有中间件
在Koa
中,中间件也是自上向下执行的
在Koa
中没有路由,默认情况它会匹配/
能在浏览器输出hello
看下面代码:
输出结果:
为什么下面输出结果是:1,3,4,2 ? koa
中间件的原理 和 express
中间件的原理不一样:
输出结果:
再看一段代码:
输出结果:
这不是和Express
一样吗?
不一样,虽然结果是一样的,但是原理不一样
源码解析
这个非常重要,好好理解
Koa
的实现主要依赖自身的koa-compose
,接下来咱们看一下这个函数的源码:
有点长不好看懂,简化之后如下:
可以看到,一个递归调用,连续调用中间件,返回一个 Promise
链
举例分析过程:
输出结果:
其实,在 compose
内部递归执行的操作后,形成多个 Promise
层层嵌套(如下面代码所示),此时 next
函数其实就是下一个中间件,await
需要等待内部的 Promise
,所以其执行结果会呈现一个剥洋葱的模式。
自己模拟compose:
输出结果:
把里面的代码简化:
再写一个:
输出结果:
使用 dispatch
当dispatch
参数是 0 的时候,输出结果:
当dispatch
参数是 1 的时候,输出结果:
当dispatch
参数是 2 的时候,输出结果:
当dispatch
参数是 3 的时候,无输出结果
如果中间件中有异步
输出结果:
使用 async+await
,仅仅是把Pomise
状态 转化 普通值
输出结果:
Koa
常用中间件
都需要 npm
安装
koa-compose
koa-router
koa-bodyparser
koa-views
把数据渲染到模板中,然后把模板返回浏览器
koa-static
托管静态资源
评论区