文中提到的koa均为koa2

提到nodejs, 想必大家都知道express和koa.

express: 大

koa: 小

比较的的是功能, 社区, 中间件,相关资源等

这里我就专门说说中间件吧, 很多人可能说express插件丰富啊. 其实除了中间件, 其余什么的和express koa本身并没有多大关系, 不都是基于nodejs http(https)的封装嘛.

express中间件是非常的丰富, 但是提个醒, express的中间件是可以跑在koa下面的.到这里就要提到 koa-connect.

那么,我们就来简单看看这个koa-connect是怎么实现的.

其源码一共才38行, 一半多注释, 3个方法.

  • koaConnect: 对外公布的方法, 对express的中间件的参数进行分析,分别调用noCallbackHandler和withCallbackHandler
  • noCallbackHandler : 处理无回调的express的中间件
  • withCallbackHandler : 处理有回调的express的中间件

    这里的回调就是有无next方法, next方法就是进入下一个中间件
/**
* If the middleware function does declare receiving the `next` callback
* assume that it's synchronous and invoke `next` ourselves
*/
function noCallbackHandler(ctx, connectMiddleware, next) {
connectMiddleware(ctx.req, ctx.res)
return next()
} /**
* The middleware function does include the `next` callback so only resolve
* the Promise when it's called. If it's never called, the middleware stack
* completion will stall
*/
function withCallbackHandler(ctx, connectMiddleware, next) {
return new Promise((resolve, reject) => {
connectMiddleware(ctx.req, ctx.res, err => {
if (err) reject(err)
else resolve(next())
})
})
} /**
* Returns a Koa middleware function that varies its async logic based on if the
* given middleware function declares at least 3 parameters, i.e. includes
* the `next` callback function
*/
function koaConnect(connectMiddleware) {
const handler = connectMiddleware.length < 3
? noCallbackHandler
: withCallbackHandler
return function koaConnect(ctx, next) {
return handler(ctx, connectMiddleware, next)
}
} module.exports = koaConnect

koaConnect方法

function koaConnect(connectMiddleware) {
const handler = connectMiddleware.length < 3
? noCallbackHandler
: withCallbackHandler
return function koaConnect(ctx, next) {
return handler(ctx, connectMiddleware, next)
}
}

kaoConnect返回的是一个koa版本的中间件.

connectMiddleware.length是express中间件参数的长度, 如果你这个中间件使用了arguments进行参数解析或者使用了rest参数, 那么这个length本身就准确了.

通过express中间件参数的长度分别调用有回调和无回调的方法.

noCallbackHandler方法

function noCallbackHandler(ctx, connectMiddleware, next) {
connectMiddleware(ctx.req, ctx.res)
return next()
}

直接调用express方法, ctx.req 和 ctx.res作为参数传入.

ctx.req: Node 的 request 对象.

ctx.res: Node 的 Reponse 对象.

这说明express的中间的req 和 res 和koa中间件的ctx.req 和res就是一个玩意.

因为express中间件没有调用next, 所以被调用完毕, 直接调用koa中间件的next

withCallbackHandler方法

function withCallbackHandler(ctx, connectMiddleware, next) {
return new Promise((resolve, reject) => {
connectMiddleware(ctx.req, ctx.res, err => {
if (err) reject(err)
else resolve(next())
})
})
}

返回一个Promise, 因为koa中有 await next()的形式调用, 这就很好的满足了需求.

express中间里面假如有第三个参数next,调用表示进入下一个中间件.

express中间件next调用的时候可以传入Error,

可以参考express error handling

app.get("/", function (req, res, next) {
fs.readFile("/file-does-not-exist", function (err, data) {
if (err) {
next(err); // Pass errors to Express.
}
else {
res.send(data);
}
});
});

回到我们的withCallbackHandler方法

这里express的中间件的next方法即为

err => {
if (err) reject(err)
else resolve(next())
}

当有错误的时候,reject

当没有错误的时候, 调用koa中间件的next, 继续下面的执行.

koa-connect就分析完毕了, 核心就两点

  1. 通过express中间件的参数长度来区分处理
  2. 改造express中间件的next方法

koa-connect源码解析的更多相关文章

  1. Koa源码解析,带你实现一个迷你版的Koa

    前言 本文是我在阅读 Koa 源码后,并实现迷你版 Koa 的过程.如果你使用过 Koa 但不知道内部的原理,我想这篇文章应该能够帮助到你,实现一个迷你版的 Koa 不会很难. 本文会循序渐进的解析内 ...

  2. Netty 源码解析(九): connect 过程和 bind 过程分析

    原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365篇原创计划”第九篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源 ...

  3. Koa源码解析

    Koa是一款设计优雅的轻量级Node.js框架,它主要提供了一套巧妙的中间件机制与简练的API封装,因此源码阅读起来也十分轻松,不论你从事前端或是后端研发,相信都会有所收获. 目录结构 首先将源码下载 ...

  4. Koa2 源码解析(1)

    Koa2 源码解析 其实本来不想写这个系列文章的,因为Koa本身很精简,一共就4个文件,千十来行代码. 但是因为想写 egg[1] 的源码解析,而egg是基于Koa2的,所以就先写个Koa2的吧,用作 ...

  5. OKHttp源码解析

    http://frodoking.github.io/2015/03/12/android-okhttp/ Android为我们提供了两种HTTP交互的方式:HttpURLConnection 和 A ...

  6. FileZilla客户端源码解析

    FileZilla客户端源码解析 FTP是TCP/IP协议组的协议,有指令通路和数据通路两条通道.一般来说,FTP标准命令TCP端口号是21,Port方式数据传输端口是20. FileZilla作为p ...

  7. 设置ZooKeeper服务器地址列表源码解析及扩展

    设置ZooKeeper服务器地址列表源码解析及扩展 ZooKeeper zooKeeper = new ZooKeeper("192.168.109.130:2181",SESSI ...

  8. Netty5客户端源码解析

    Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...

  9. Gin框架源码解析

    Gin框架源码解析 Gin框架是golang的一个常用的web框架,最近一个项目中需要使用到它,所以对这个框架进行了学习.gin包非常短小精悍,不过主要包含的路由,中间件,日志都有了.我们可以追着代码 ...

  10. Android八门神器(一): OkHttp框架源码解析

    HTTP是我们交换数据和媒体流的现代应用网络,有效利用HTTP可以使我们节省带宽和更快地加载数据,Square公司开源的OkHttp网络请求是有效率的HTTP客户端.之前的知识面仅限于框架API的调用 ...

随机推荐

  1. Shell循环输入符合条件为止

    提供用户输入,直到输入d/D/r/R为止. #!/bin/bash ]; do echo -n "(D)ebug or (R)elease?" read select_build_ ...

  2. Java-Java面向对象程序设计

    2017-10-09 17:23:52 在面向对象技术中,将客观世界中的一个事物作为一个对象来考虑,比如有个张先生,他就是一个对象.每个对象都有自己的属性和行为.张先生的属性根据需要有姓名.性别.身高 ...

  3. spring boot: spring-data-jpa (Repository/CrudRepository) 数据库操作, @Entity实体类持久化

    SpringBoot实现的JPA封装了JPA的特性, Repository是封装了jpa的特性(我是这么理解的) 1在pom.xml引入mysql, spring-data-jpa依赖 2.在src/ ...

  4. Android之设计模式

    设计模式的概念 1.基本定义:设计模式(Design pattern)是一套被反复使用的代码设计经验的总结.使用设计模式的目的是为了可重用代码.让代码更容易被他人理解.设计模式是是软件工程的基石脉络, ...

  5. android沉浸状态栏和顶部状态栏背景色的设置

    法一: 现在很多应用都引用了沉浸式状态栏,如QQ,效果下图: 这样的效果很酷炫,其实设置很简单. 不过要说明的是,这种效果只能在API19以及以上版本中才能够做到. 如果想让界面Activity中实现 ...

  6. Java 访问控制关键字

    public, private, protected 在控制上有什么区别和不同请参考下面的说明. 请参考下图的说明. 和下面的一个说明: │ Class │ Package │ Subclass │ ...

  7. 『PyTorch』第五弹_深入理解autograd_下:函数扩展&高阶导数

    一.封装新的PyTorch函数 继承Function类 forward:输入Variable->中间计算Tensor->输出Variable backward:均使用Variable 线性 ...

  8. 14西安区域赛C - The Problem Needs 3D Arrays

    最大密度子图裸题,详情请见胡博涛论文: https://wenku.baidu.com/view/986baf00b52acfc789ebc9a9.html 不加当前弧优化t到死= = //#prag ...

  9. form数据请求参数格式

    请求后台参数格式问题 当请求后台传递参数时,有多中类型,而每一种都需要前后台进行配合,而这有时候会很简单,有时候却十分困难,记录一下,以备后期深究 数据 后台需要的数据 form表单 嵌套数据,第二层 ...

  10. js设计模式-观察者模式

    定义: 观察者模式又叫发布订阅模式,它定义了对象间的一种一对多的依赖关系.观察者模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间的互相通信. 思路 定义一个对象,在对象中实 ...