预计写的这十几篇文章是基于 Koa initial commit 版本, 会逐渐对这几年来提交的 1000 多个 Commit 做个分析, 目的是希望大家了解一个开源项目从诞生到成熟涉及的方方面面.
Koa 源码中有许多堪称惊艳的代码片段, 这里先举一个 HTTP 状态码的例子.
在上一篇文章中介绍了 koa 之实现, 其中提出了在响应请求的过程中, 如何正确的定义 http 状态码这个问题.
STATUS CODE
来看一下 Node.JS 中 statusCode 的定义
- const STATUS_CODES: {
- [errorCode: number]: string | undefined;
- [errorCode: string]: string | undefined;
- };
从定义中看, STATUS_CODES 是一个字面量, key 的类型是 string | number, value 类型是 string.
它在 Node.JS 标准库中, 是这样的一个对象:
- { '100': 'Continue',
- '101': 'Switching Protocols',
- '102': 'Processing',
- '200': 'OK',
- '201': 'Created',
- '202': 'Accepted',
- '203': 'Non-Authoritative Information',
- '204': 'No Content',
- '205': 'Reset Content',
- '206': 'Partial Content',
- '207': 'Multi-Status',
- '208': 'Already Reported',
- '226': 'IM Used',
- '300': 'Multiple Choices',
- '301': 'Moved Permanently',
- '302': 'Found',
- '303': 'See Other',
- '304': 'Not Modified',
- '305': 'Use Proxy',
- '307': 'Temporary Redirect',
- '308': 'Permanent Redirect',
- '400': 'Bad Request',
- '401': 'Unauthorized',
- '402': 'Payment Required',
- '403': 'Forbidden',
- '404': 'Not Found',
- ......
- }
题外话, Node.JS 实现 http 模块其实是在 C++ 上封装了一层代码, 具体的底层实现, 可以看下这篇文章.
Koa 的实现
在 Koa 最初版本中, STATUS_CODE 的作用是在 Context.JS 中的 status 方法和 statusString 方法. 我们来看他们的作用.
- get statusString() {
- return http.STATUS_CODES[this.status];
- },
- set status(val) {
- if ('string' == typeof val) {
- var n = statuses[val];
- if (!n) throw new Error(statusError(val));
- val = n;
- }
- this.res.statusCode = val;
- }
从代码中可以看到, Koa 希望 Context 类能够判断
状态码是否存在
实际意义与状态码的对应
这里主要是在 status 方法中会对传入的 val 值进行判断, 如果传入的是字符串, 则需要获取对应的 状态码. 效果大概要达到 status['Not Found'] == 404 这样. 这其实就是对象的 反向映射的处理.
来看 Koa 是如何实现的:
- var http = require('http');
- var codes = http.STATUS_CODES;
- /**
- * Produce exports[STATUS] = CODE map.
- */
- Object.keys(codes).forEach(function(code){
- var n = ~~code;
- var s = codes[n].toLowerCase();
- exports[s] = n;
- });
在大多数在 2013 年使用 JS 语言的人来讲, 做一次简单反向映射的操作, 可不是这三行语句. 当然, 对于现在的人来讲, 用类函数式写法可以一行了事.
话题跑远了, 这里的经典操作就是
使用 Object.keys 来进行遍历并获取 code 值
利用 JS 的类型推导来将字符串转换成数字
当然, 实际上还有一些人并不知道为什么 JS 可以这样将字符串转换成数字 (底层实现). 或者是不知道为什么 5 取反会得 -6...
总结
对现在来看, 这样的写法确实显得有些罗嗦. 如果场景放在 2013 年, 这样的操作还算能体现出扎实的基本功.
参考 & 引用
http 的 status_code
走进 Node.JS 之 HTTP 实现分析
来源: http://www.jianshu.com/p/6538b039fcbc