摘要:本筆記共四篇源碼閱讀筆記源碼閱讀筆記源碼閱讀筆記服務器啟動與請求處理源碼閱讀筆記對象起因前兩天終于把自己一直想讀的源代碼讀了一遍。首先放上關鍵的源代碼在上一篇源碼閱讀筆記服務器啟動與請求處理中,我們已經分析了的作用。
起因本筆記共四篇
Koa源碼閱讀筆記(1) -- co
Koa源碼閱讀筆記(2) -- compose
Koa源碼閱讀筆記(3) -- 服務器の啟動與請求處理
Koa源碼閱讀筆記(4) -- ctx對象
前兩天終于把自己一直想讀的Koa源代碼讀了一遍。
今天就要來分析Koa的ctx對象,也就是在寫中間件和處理請求和響應時的那個this對象。
而這個this對象,也是和Express的重要區別之一。不用再區分req,res(雖然還是得知道),一個this對象就能調用所有方法。
在實際開發中,是非常便利的。
在這兒則需要談一談Koa1和Koa2調用this對象的區別。
Koa1在調用時,使用的是this,而Koa2則是ctx。
// Koa1 app.use(function * (next) { this.body = "hello world" yield next })
// Koa2 app.use(async (ctx, next) => { ctx.body = "hello world" await next() })
使用方式,只是把this換成了ctx。
具體為什么出現ctx和next,之前的文章koa-compose的分析有寫。
這兒繼續以Koa1為例,因為看得懂Koa1源代碼的,看Koa2的源碼自然也不難。
首先放上關鍵的源代碼:
app.callback = function(){ var fn = co.wrap(compose(this.middleware)); var self = this; return function(req, res){ res.statusCode = 404; var ctx = self.createContext(req, res); onFinished(res, ctx.onerror); fn.call(ctx).then(function () { respond.call(ctx); }).catch(ctx.onerror); } };
在上一篇Koa源碼閱讀筆記(3) -- 服務器の啟動與請求處理中,我們已經分析了fn的作用。
而onFinished則會在請求完成時調用,剩下的則是調用中間件去處理響應。
同時var ctx = self.createContext(req, res);這一句,不看createContext這個函數,應該也能猜出它的作用。
之后的fn.call(ctx)則說明了中間件中this的來源。
在這兒不得不感嘆一句,JavaScript的this真的是太靈活了,配合閉包,call,apply等,簡直擁有無限魔力。
貼出相關的源代碼:
var response = require("./response"); var context = require("./context"); var request = require("./request"); /** * Initialize a new context. * * @api private */ app.createContext = function(req, res){ var context = Object.create(this.context); var request = context.request = Object.create(this.request); var response = context.response = Object.create(this.response); context.app = request.app = response.app = this; context.req = request.req = response.req = req; context.res = request.res = response.res = res; request.ctx = response.ctx = context; request.response = response; response.request = request; context.onerror = context.onerror.bind(context); context.originalUrl = request.originalUrl = req.url; context.cookies = new Cookies(req, res, { keys: this.keys, secure: request.secure }); context.accept = request.accept = accepts(req); context.state = {}; return context; };
雖然看上去有點繞,但是仔細看看,還是不難的。
之前說過,Koa的源碼簡潔,一共就4個文件。
除了主要的Application.js, 剩下就都是與請求和響應相關的了。
這兒,因為每次都要創建并調用ctx對象。為了避免影響原有的context,request,response對象。
這兒采用了Object.create()來克隆對象。
首先就來分析,最開始的context.js。
context的實現很簡單,但有意思的地方在于delegate這個地方。
就如下圖所示:
我看了delegate這個源代碼,功能是把context中相應的方法調用和屬性讀取,委托至某個對象中。
而不用自己一個一個的寫apply,call等。
關于request和response,我這兒就不詳細寫了。
在這兒放一張圖足以。
實際上,request和response是通過getter和setter,來實現存取不同屬性的功能。
另外,通過剛才說的delegate方法,則使用ctx對象時,便能自動通過getter和setter獲取想要的內容。
這一篇很簡單,其實也沒啥可以說的。
因為Koa除了中間件部分看起來復雜,其它地方還是很簡潔明了的。
學習源代碼的過程中,也發現了很多優雅的寫法,算是開拓了自己的眼界。
從會寫到寫好,看來還要挺長一段時間的。
前端路漫漫,且行且歌。
最后附上本人博客地址和原文鏈接,希望能與各位多多交流。
Lxxyx的前端樂園
原文鏈接:Koa源碼閱讀筆記(4) -- ctx對象
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90861.html
摘要:本筆記共四篇源碼閱讀筆記源碼閱讀筆記源碼閱讀筆記服務器啟動與請求處理源碼閱讀筆記對象起因前兩天閱讀了的基礎,和中間件的基礎。的前端樂園原文鏈接源碼閱讀筆記服務器啟動與請求處理 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4) -- ctx對象 起因 前兩天閱讀了K...
摘要:正好自己之前也想看的源代碼,所以趁著這個機會,一口氣將其讀完。源碼解讀的源代碼十分簡潔,一共才兩百余行。結語的源代碼讀取來不難,但其處理方式卻令人贊嘆。而且閱讀的源代碼,是閱讀源碼的必經之路。 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4) -- ctx對象 起...
摘要:引言最近空閑時間讀了一下的源碼在閱讀的源碼的過程中,我的感受是代碼簡潔思路清晰不得不佩服大神的水平。調用的時候就跟有區別使用必須使用來調用除了上面的的構造函數外,還暴露了一些公用的,比如兩個常見的,一個是,一個是。 引言 最近空閑時間讀了一下Koa2的源碼;在閱讀Koa2(version 2.2.0)的源碼的過程中,我的感受是代碼簡潔、思路清晰(不得不佩服大神的水平)。下面是我讀完之后...
摘要:于是抱著知其然也要知其所以然的想法,開始閱讀的源代碼。問題讀源代碼時,自然是帶著諸多問題的。源代碼如下在被處理完后,每當有新請求,便會調用,去處理請求。接下來會繼續寫一些閱讀筆記,因為看的源代碼確實是獲益匪淺。 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4) -...
摘要:接上次挖的坑,對相關的源碼進行分析第一篇。和同為一批人進行開發,與相比,顯得非常的迷你。在接收到一個請求后,會拿之前提到的與來創建本次請求所使用的上下文。以及如果沒有手動指定,會默認指定為。 接上次挖的坑,對koa2.x相關的源碼進行分析 第一篇。 不得不說,koa是一個很輕量、很優雅的http框架,尤其是在2.x以后移除了co的引入,使其代碼變得更為清晰。 express和ko...
閱讀 1979·2019-08-30 15:54
閱讀 3602·2019-08-29 13:07
閱讀 3129·2019-08-29 12:39
閱讀 1793·2019-08-26 12:13
閱讀 1552·2019-08-23 18:31
閱讀 2164·2019-08-23 18:05
閱讀 1852·2019-08-23 18:00
閱讀 1049·2019-08-23 17:15