预计写的这十几篇文章是基于Koa
initial commit
版本,会逐渐对这几年来提交的1000多个Commit做个分析,目的是希望大家了解一个开源项目从诞生到成熟涉及的方方面面。
Koa源码中有许多堪称惊艳的代码片段,这里先举一个HTTP状态码的例子。
在上一篇文章中介绍了koa之实现,其中提出了在响应请求的过程中,如何正确的定义http状态码这个问题。
STATUS CODE
来看一下nodejs
中 statusCode
的定义
const STATUS_CODES: {
[errorCode: number]: string | undefined;
[errorCode: string]: string | undefined;
};
从定义中看,STATUS_CODES
是一个字面量, key
的类型是 string | number
, value
类型是 string
。
它在nodejs
标准库中,是这样的一个对象:
{ '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',
……
}
题外话,nodejs
实现 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年,这样的操作还算能体现出扎实的基本功。