Koa 依赖的库 http-errors 和 http-assert

这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

本文为 koa 依赖系列文章,前几篇也可以在站内查看:

调用 context 下 throw 方法时会抛出一个 HttpError,这个 HttpError 是通过 http-errors 提供的 createError 创建的,同时 Koa 也在内部转发导出了 HttpError 类型,我们可以直接使用。

HttpError 类型是通过调用 createHttpErrorConstructor 方法构造的,createHttpErrorConstructor 内部定义了一个抽象类 HttpError,这个类继承自 Error,需要使用 createError 创建 HttpError。

function createHttpErrorConstructor () {
  function HttpError () {
    throw new TypeError('cannot construct abstract class')
  }

  inherits(HttpError, Error)

  return HttpError
}
复制代码

createError 的逻辑比较复杂,前面是一些列 arguments 的处理,处理的细节可以忽略,可以看到这里的比较重要的一个参数是 status,默认的状态码是 500,也可以通过参数传入其他状态码值,最终 constructor 是根据状态码来获取的:

var HttpError = createError[status] || createError[codeClass(status)]
复制代码

createError 上面的附加信息是通过 populateConstructorExports 构造的:

populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError)
复制代码

http 错误可以分为客户端错误和服务器错误两种,对应状态码为 4XX 和 5XX,因此这里会首先对传入的错误进行类型划分:

function codeClass (status) {
  return Number(String(status).charAt(0) + '00')
}

switch (codeClass(code)) {
	case 400:
		CodeError = createClientErrorConstructor(HttpError, name, code)
		break
	case 500:
		CodeError = createServerErrorConstructor(HttpError, name, code)
		break
}
复制代码

这里客户端和服务端的错误创建的是两种不同类型,而对应的错误名会使用 statuses 库把状态码转化为字符串信息。

ClientError 和 ServerError 都是 Error,原型的修改是通过 setprototypeof 库来实现的,它的内部逻辑也比较简单:

'use strict'
/* eslint no-proto: 0 */
module.exports = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array ? setProtoOf : mixinProperties)

function setProtoOf (obj, proto) {
  obj.__proto__ = proto
  return obj
}

function mixinProperties (obj, proto) {
  for (var prop in proto) {
    if (!Object.prototype.hasOwnProperty.call(obj, prop)) {
      obj[prop] = proto[prop]
    }
  }
  return obj
}
复制代码

定义好类型后,error 数据信息是使用 Error.captureStackTrace 来设置的。

http-errors 的内部主要就是类型的定义逻辑,由于没有使用 class,因此在内部可以看到使用 js 函数进行集成构造等操作,有相关需要可以参考。errors 相关的内容就这么多,接下来看一下 assert 相关的逻辑。

context 上的 assert 方法是 http-assert 包提供的,这个包导出了 assert 函数,传入的内容不是 truthy 时抛出一个 http error,这个错误就是调用上面的 http-errors 中 createError 方法创建的:

function assert (value, status, msg, opts) {
  if (value) return
  throw createError(status, msg, opts)
}
复制代码

除了默认的 assert 函数,上面还导出了一系列辅助函数:fail、equal、notEqual、ok、strictEqual、notStrictEqual、deepEqual、notDeepEqual。这里可以从函数名看出来对应的功能,其中 ok 与默认导出的 assert 效果相同,fail 直接抛 error,三组 equal 的区别在于判断方式不同:

  • equal & notEqual:使用 == 判断。
  • strictEqual & notStrictEqual:使用 === 判断。
  • deepEqual & notDeepEqual:调用 deep-equal 库判断,这是一个判断相等的库,可以对两个对象的内容进行递归比较。

以上就是 http-errors 和 http-assert 的全部内容了,这两部分在 koa 作为直接导出的 API,实际应用还是比较多的,尤其是在测试场景下。

猜你喜欢

转载自juejin.im/post/7032325648144154661
koa