Koa 依赖的库 http-errors 和 http-assert
调用 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,实际应用还是比较多的,尤其是在测试场景下。
作者:丨隋堤倦客丨
链接:https://juejin.cn/post/7032325648144154661