国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一步步去閱讀koa源碼,整體架構(gòu)分析

chaos_G / 422人閱讀

摘要:閱讀好的框架的源碼有很多好處,從大神的視角去理解整個(gè)框架的設(shè)計(jì)思想。使用其實(shí)某個(gè)框架閱讀源碼的時(shí)候,首先我們要會(huì)去用這個(gè)框架,因?yàn)橛昧宋覀儾胖溃硞€(gè)是怎么用,哪里有坑,哪里設(shè)計(jì)的精妙。

閱讀好的框架的源碼有很多好處,從大神的視角去理解整個(gè)框架的設(shè)計(jì)思想。大到架構(gòu)設(shè)計(jì),小到可取的命名風(fēng)格,還有設(shè)計(jì)模式、實(shí)現(xiàn)某類功能使用到的數(shù)據(jù)結(jié)構(gòu)和算法等等。
使用koa

其實(shí)某個(gè)框架閱讀源碼的時(shí)候,首先我們要會(huì)去用這個(gè)框架,因?yàn)橛昧宋覀儾胖溃硞€(gè)API是怎么用,哪里有坑,哪里設(shè)計(jì)的精妙。

下面我們就簡(jiǎn)單用一下koa這個(gè)框架,如下代碼

const Koa = require("koa")
const app = new Koa()
app.use(async (ctx, next) => {
  ctx.body = "Hello World"
})
app.listen(4002)

運(yùn)行結(jié)果

瓦特??這個(gè)服務(wù)會(huì)涉及到從請(qǐng)求到響應(yīng)返回?cái)?shù)據(jù),就這幾行代碼?? 是的,你沒(méi)有看錯(cuò),就是單單這幾行代碼就可以搭建了一個(gè)服務(wù)器。

下面我們看看一探究竟。

閱讀源碼

去到node_modules文件夾下找到koa模塊,先喵幾眼README.md文件,里面介紹了koa的一些安裝、用法、插件等等,這里我們跳過(guò),然后轉(zhuǎn)到package.json如下圖

看到package.json里面的"main": "lib/application.js"沒(méi)錯(cuò),這就是我們的入口,在lib文件夾下面,我們看到里面有application.jscontext.jsrequrest.jsresponse.js。下面經(jīng)過(guò)我修改簡(jiǎn)化去掉注釋application.js就只有68行代碼。閱讀起來(lái)可以說(shuō)是非常簡(jiǎn)單了。如下圖:

第一步是我們引入各種主要依賴

// 引入有很多 我只挑我閱讀主要框架的代碼模塊

const response = require("./response"); // 處理response對(duì)象
const compose = require("koa-compose"); // 合并處理中間件函數(shù)
const context = require("./context"); // 整合處理context對(duì)象
const request = require("./request"); // 整合處理request對(duì)象
const http = require("http"); // node的 http原生模塊

以上就是我們的主要依賴

Application的對(duì)象中,有constructor函數(shù),這個(gè)主要是初始化Application對(duì)象,生成context對(duì)象、request對(duì)象、response對(duì)象

module.exports = class Application extends Emitter {
  // 初始化 Application
  constructor() {
    super(); // 繼承Emitter
    this.middleware = []; // 初始化middleware為空數(shù)組
    this.context = Object.create(context); // 生成context對(duì)象
    this.request = Object.create(request); // 生成request對(duì)象
    this.response = Object.create(response); // 生成response對(duì)象
  }
}

閱讀源碼,我們先不要去扣細(xì)節(jié),比如說(shuō)Object.create(context)生產(chǎn)的對(duì)象是什么?this.request對(duì)象下面又有什么東西???,我們現(xiàn)在主要知道的是、this.context是能獲取或者設(shè)置請(qǐng)求和響應(yīng)的信息的一個(gè)對(duì)象,。this.request是請(qǐng)求的對(duì)象、里面可以設(shè)置或者獲取請(qǐng)求信息的一個(gè)對(duì)象、this.response是響應(yīng)請(qǐng)求對(duì)象、里面可以設(shè)置或者獲取響應(yīng)參數(shù)和值的一個(gè)對(duì)象。大概先了解就可以了。繼續(xù)往下看。

在上面運(yùn)用的時(shí)候,用到了app.use(fn)app.listen(4002) 我們看看,源碼里面試這樣子的

module.exports = class Application extends Emitter {
  // 初始化 Application
  constructor() {
    ...
  }
  listen(...args) {
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }
  use(fn) {
    this.middleware.push(fn);
    return this;
  }

上面的代碼很簡(jiǎn)單 use函數(shù)就是把傳入的fn 推入到this.middleware的數(shù)組中,然后返回this,方便鏈?zhǔn)秸{(diào)用。

然后在listen里面用node原生的http模塊創(chuàng)建一個(gè)server,在這里順便說(shuō)一下,原生 http創(chuàng)建一個(gè)服務(wù)是這樣子滴

const http = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("okay");
});
http.listen(8000)

繼續(xù)看代碼 ,在創(chuàng)建服務(wù)的時(shí)候,參數(shù)里面調(diào)用了一個(gè)this.callback()函數(shù),下面我們看看這個(gè)函數(shù)究竟是怎么樣子的。

module.exports = class Application extends Emitter {
  // 初始化 Application
  constructor() {
    ...
  }
  listen(...args) {
    ...
  }
  use(fn) {
    ...
  }

  callback() {
    const fn = compose(this.middleware); // 集中處理中間件數(shù)組
    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res); // 整合req、res、context、request、response
      return this.handleRequest(ctx, fn); // 返回handleRequest
    };
    return handleRequest;
  }
    
  handleRequest(ctx, fnMiddleware) {
    const handleResponse = () => respond(ctx); // 最終響應(yīng)函數(shù)
    return fnMiddleware(ctx).then(handleResponse) // 處理完中間件,然后傳到下一響應(yīng)函數(shù)
  }
  // 創(chuàng)建整合新的 context.
  createContext(req, res) {
    const context = Object.create(this.context);
    const request = context.request = Object.create(this.request);
    const 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.originalUrl = request.originalUrl = req.url;
    context.cookies = new Cookies(req, res, {
      keys: this.keys,
      secure: request.secure
    });
    request.ip = request.ips[0] || req.socket.remoteAddress || "";
    context.accept = request.accept = accepts(req);
    context.state = {};
    return context;
  }
};

上面我們可以看出在callback函數(shù)里面有一個(gè)const fn = compose(this.middleware); 這個(gè)函數(shù)就是把this.middleware數(shù)組傳進(jìn)去,然后集中處理中間件,然后會(huì)返回處理完中間件的fn。

繼續(xù)下一行

const handleRequest = (req, res) => {
  const ctx = this.createContext(req, res);
  return this.handleRequest(ctx, fn);
};

繼續(xù)進(jìn)入到handleRequest函數(shù)里面的const ctx = this.createContext(req, res);這個(gè)把原生的http的請(qǐng)求對(duì)象req響應(yīng)對(duì)象res作為參數(shù)傳進(jìn)去,然后在createContext函數(shù)(看上面最大那坨代碼)在里面,把this.requestthis.responsethis.context請(qǐng)求對(duì)象req響應(yīng)對(duì)象res都整,做各種整合、處理得到新的context對(duì)象返回出去。

也就是強(qiáng)大的ctx,得到ctx之后,下一行返回return this.handleRequest(ctx, fn);

this.handleRequest(ctx, fn)代碼如下

handleRequest(ctx, fnMiddleware) {
    const handleResponse = () => respond(ctx);
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}

這個(gè)函數(shù) 就是處理完中間件處理之后的返回的函數(shù)把ctx傳下去,最后流通到respond(ctx);這個(gè)函數(shù),

那么我們看看這個(gè)函數(shù)被我簡(jiǎn)化后是怎么樣子的,如下

// 一些容錯(cuò)判斷或者提示我全部刪了
function respond(ctx) {
  const res = ctx.res;
  let body = ctx.body;
  res.end(body);
}

通過(guò)ctx拿到響應(yīng)對(duì)象,和響應(yīng)值、通過(guò)end方法會(huì)通知服務(wù)器,所有響應(yīng)頭和響應(yīng)主體都已被發(fā)送,即服務(wù)器將其視為已完成。看上面原生的http的服務(wù)方法。

最后附上一個(gè)流程圖

這個(gè)只是介紹application整個(gè)流程,還有很多細(xì)節(jié)都沒(méi)有一一介紹到,比如、創(chuàng)建contextrequestresponse對(duì)象是怎么樣子的呀?中間件是如何集中層層深入處理然后返回的呀?等等這些細(xì)節(jié)都會(huì)在下一篇會(huì)講到(最近公司業(yè)務(wù)非常忙,不知道到猴年馬月)。

寫的不好的地方,讓大家賤笑了。

然后最后安利一波博客,喜歡的小哥哥小姐姐可以star 喲

websit: https://github.com/naihe138/naice-blog

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/52361.html

相關(guān)文章

  • 步步閱讀koa源碼整體架構(gòu)分析

    摘要:閱讀好的框架的源碼有很多好處,從大神的視角去理解整個(gè)框架的設(shè)計(jì)思想。使用其實(shí)某個(gè)框架閱讀源碼的時(shí)候,首先我們要會(huì)去用這個(gè)框架,因?yàn)橛昧宋覀儾胖溃硞€(gè)是怎么用,哪里有坑,哪里設(shè)計(jì)的精妙。 閱讀好的框架的源碼有很多好處,從大神的視角去理解整個(gè)框架的設(shè)計(jì)思想。大到架構(gòu)設(shè)計(jì),小到可取的命名風(fēng)格,還有設(shè)計(jì)模式、實(shí)現(xiàn)某類功能使用到的數(shù)據(jù)結(jié)構(gòu)和算法等等。 使用koa 其實(shí)某個(gè)框架閱讀源碼的時(shí)候,首...

    haoguo 評(píng)論0 收藏0
  • 步步閱讀koa源碼,中間件執(zhí)行原理

    摘要:設(shè)置了一個(gè)出事索引值調(diào)用函數(shù),開(kāi)始時(shí)候傳進(jìn)去聲明函數(shù),把傳進(jìn)來(lái)的賦值給拿出第個(gè)中間件函數(shù),賦值給判斷如果等于的長(zhǎng)度就把賦值給如果是假的返回一個(gè)同時(shí)執(zhí)行,也就是中間件,把函數(shù)傳遞到里面遞歸調(diào)用自己上面的代碼是這個(gè)部分的精華。 koa的中間件執(zhí)行的流程控制,代碼的是非常精妙的。由下面的一張洋蔥模型的圖來(lái)形容,記住這張圖。 showImg(https://segmentfault.com/i...

    WelliJhon 評(píng)論0 收藏0
  • B站Up主-山地人-這位老哥2019年的前端自學(xué)計(jì)劃進(jìn)展如何?——講個(gè)B站Up主自學(xué)前端85天的故

    摘要:前言自從上次在掘金發(fā)布年山地人的前端完整自學(xué)計(jì)劃講一個(gè)站主山地人的天前端自學(xué)故事以來(lái),一眨眼山地人老哥在站做主已經(jīng)有天了。所以這個(gè)體系里的一些框架包括也是山地人年自學(xué)計(jì)劃的一部分。月底,山地人老哥開(kāi)啟了的兩個(gè)專題。 前言 自從上次在掘金發(fā)布【2019年山地人的前端完整自學(xué)計(jì)劃——講一個(gè)B站UP主山地人的40天前端自學(xué)故事】 以來(lái),一眨眼山地人老哥在B站做Up主已經(jīng)有85天了。 時(shí)隔一個(gè)...

    cocopeak 評(píng)論0 收藏0
  • 教你從寫個(gè)迷你koa-router到閱讀koa-router源碼

    摘要:本打算教一步步實(shí)現(xiàn),因?yàn)橐忉尩奶嗔耍韵群?jiǎn)化成版本,從實(shí)現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。 本打算教一步步實(shí)現(xiàn)koa-router,因?yàn)橐忉尩奶嗔耍韵群?jiǎn)化成mini版本,從實(shí)現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。希望你之前有讀過(guò)koa源碼,沒(méi)有的話,給你鏈接 最核心需求-路由匹配 router最重要的就是路由匹配,我們就從最核心的入手 router.get...

    yzzz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<