Node.js中request+response數據結構分解

一個簡單的Node.js應用,只需要如下兩行代碼即可構建。

let fn = (req,res)=>res.end(hellp);n let server = http.createServer(fn).listen(7000)n

上面的代碼容易讓很多Node開發形而上學而忽略它的本質。

實際上由於Node在API設計上大量採用了facade模式,使得不少api的使用實際上只是調用另一個api而已。比如res.end(hello),等價於res.write(hello)+res.end()。

開頭的那段代碼,在Node實際,內部上是個在request事件上掛載listener的模型。

let fn = (req,res)=>res.end();n let server = http.createServer()n server.on(request,fn)n

在我專欄的上篇文章,我分享了如何採用Symbol來實現Promise。在文章寫完後,同事們的反饋是太過晦澀、對讀者的要求也比較高。所以這篇文章,我改進了分享形式,不採用代碼模式而採用圖形化數據結構來分享Node知識。

本文的主要知識點在於request和response對象。

我採用tree的結構展示了這兩個對象原型鏈中http_out_going、stream、eventEmitter等的繼承關係。

正文為request和response對象的樹狀數據結構,在這個tree中我只展示了public方法,私有方法並未列出,希望Node開發者在閱讀本文時有所甄別。

這篇文章的受眾是有Node開發經驗的讀者。

request對象

request對象實現了Readable Stream的介面

|- IncomingMessagen|- |- clientn|- |- socket (客戶端和server的request socket)n|- |- connectionn|- |n|- |- headersn|- |- |- accept:*/*n|- |- |- host:localhost:7000n|- |- |- user-agent:curl/7.43.0n|- |n|- |- httpVersion:"1.1"n|- |n|- |- upgrade: falsen|- |- url:"/"n|- |n|- |- |- 原型鏈 Readablen|- |- |-n|- |- |- constructor: Readable(options)n|- |- |- destroy(error)n|- |- |- read(n)n|- |- |- setTimeout(msecs, callback)n|- |- |n|- |- |- |- 原型鏈 Streamn|- |- |- |- addListener(event,fn)n|- |- |- |- on(event,fn)n|- |- |- |- pipe(dest, pipeOpts)n|- |- |- |- pause()n|- |- |- |- push(chunk, encoding)n|- |- |- |- read(n)n|- |- |- |- resume()n|- |- |- |- setEncoding(enc)n|- |- |- |- unpipe(dest)n|- |- |- |- unshift(chunk)n|- |- |- |- wrap(stream)n|- |- |- |n|- |- |- |- 原型鏈 EventEmittern|- |- |- |- |- addListener(event,fn)n|- |- |- |- |- on(type, listener)n|- |- |- |- |- once(type, listener)n|- |- |- |- |- emit(type)n|- |- |- |- |- getMaxListners()n|- |- |- |- |- listenerCount(type)n|- |- |- |- |- listeners(type)n|- |- |- |- |- prependListener(type,listener)n|- |- |- |- |- prependOnceListener(type,listener)n|- |- |- |- |- removeAllListeners(type)n|- |- |- |- |- removeListener(type,listener)n|- |- |- |- |- setMaxListener(n)n

response

response對象實現了Writable Stream的介面,但它並未繼承Writable Stream

|- ServerResponsen|- |- socket (客戶端和server的request socket)n|- |- connectionn|- |n|- |- _headers:nulln|- |n|- |- chunkEncoding:falsen|- |n|- |- upgrading: falsen|- |n|- |- useChunkedEncodingByDefault:truen|- |n|- |- writable:truen|- |n|- |- |- 原型鏈 OutgoingMessagen|- |- |n|- |- |- constructor: OutgoingMessagen|- |- |- writeHead(statusCode,reason,obj)n|- |- |- writeHeader()n|- |- |- writeContinue(cb)n|- |- |- statusCode:200n|- |- |- statusMessage:undefinedn|- |- |- writeContinue(cb)n|- |- |n|- |- |- writeAble Stream的介面實現n|- |- |- |- addTrailers(headers)n|- |- |- |- destroy(error)n|- |- |- |- end(data, encoding, callback)n|- |- |- |- write(chunk, encoding, callback)n|- |- |- |- flush()n|- |- |- |- flushHeaders()n|- |- |- |- headerSentn|- |- |- |- removeHeader(name)n|- |- |- |- setHeader(name,value)n|- |- |- |- setTimeout(msecs, callback)n|- |- |- |- pipe(dest,options)n|- |- |- |n|- |- |- |- 原型鏈 EventEmittern|- |- |- |- |- addListener(event,fn)n|- |- |- |- |- on(type, listener)n|- |- |- |- |- once(type, listener)n|- |- |- |- |- emit(type)n|- |- |- |- |- getMaxListners()n|- |- |- |- |- listenerCount(type)n|- |- |- |- |- listeners(type)n|- |- |- |- |- prependListener(type,listener)n|- |- |- |- |- prependOnceListener(type,listener)n|- |- |- |- |- removeAllListeners(type)n|- |- |- |- |- removeListener(type,listener)n|- |- |- |- |- setMaxListener(n)n

結語

如上列出的數據結構即為request和response的依賴繼承關係,開發者可以對照這個數據結構表調用對應的方法構建你的Node.js應用。

如果讀者想實踐上面列出的繼承關係,可以看這個項目full-stack-practice。

最後,如果筆者在邏輯上存在理解錯誤,請在評論區指出。

下一篇文章,我將繼續分享關於Node stream的個人研究。

歡迎讀者關注我的知乎和我的專欄。

推薦閱讀:

Node.js 性能調優之CPU篇(二)——v8-profiler
酷站推薦 - mermaidjs.github.io - diagrams and flowcharts from markdown text
Node.js v8.x 新特性 Async Hook 簡介
如何使用koa2+es6/7打造高質量Restful API
Nodejs系列課程,從入門到進階幫你打通全棧

TAG:Nodejs | 前端开发 | 后端技术 |