Koa實現細節之HTTP狀態碼
預計寫的這十幾篇文章是基於Koainitial 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
語言的人來講,做一次簡單反向對映的操作,可不是這三行語句。當然,對於現在的人來講, 用類函式式寫法可以一行了事。
話題跑遠了, 這裡的經典操作就是
js
當然,實際上還有一些人並不知道為什麼js可以這樣將字串轉換成數字(底層實現)。或者是不知道為什麼5
取反會得-6
...
總結
對現在來看,這樣的寫法確實顯得有些羅嗦。如果場景放在2013年,這樣的操作還算能體現出紮實的基本功。