成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

代碼改變世界 | 如何封裝一個(gè)簡(jiǎn)單的 Koa

yagami / 2800人閱讀

摘要:改造成服務(wù)類接下來在這個(gè)基礎(chǔ)上改造一下,把封裝成一個(gè)對(duì)象。新建,測(cè)試代碼如下封裝上下文對(duì)象為了實(shí)現(xiàn)類似那種這樣的方式,先來新建個(gè)文件,,。


下面給大家?guī)恚悍庋b一個(gè)簡(jiǎn)單的 Koa
Koa 是基于 Node.js 平臺(tái)的下一代 web 開發(fā)框架
Koa 是一個(gè)新的 web 框架,可以快速而愉快地編寫服務(wù)端應(yīng)用程序,本文將跟大家一起學(xué)習(xí):封裝一個(gè)簡(jiǎn)單的 Koa
一個(gè)簡(jiǎn)單的 http 服務(wù)
使用 node 提供的 http 模塊,可以很容易的實(shí)現(xiàn)一個(gè)基本的 http 服務(wù)器,新建一個(gè) application.js 文件,內(nèi)容如下:

const http = require("http")

const server = http.createServer((req, res) => {
  res.end("Hello, Fq!")
})

server.listen(8080, () => {
  console.info("Server is running at 8080")
})

之后通過 node 來啟動(dòng)這個(gè)腳本,打開瀏覽器 輸入地址 localhost:8080,即可訪問。
改造成服務(wù)類
接下來在這個(gè)基礎(chǔ)上改造一下,把 server 封裝成一個(gè)對(duì)象。

const http = require("http")

class Application () {
  constructor () {}
  use (cb) {
    this.callback = cb
  }
  listen (...args) {
    const server = http.createServer((req, res) => {
      this.callback(req, res)
    })
    server.listen(...args)
  }
}

module.exports = Application

新建 server.js ,測(cè)試代碼如下:

const Koa = require("./application.js")
const app = new Koa()

app.use((req, res) => {
  res.end("Hello, Fq!")
})

app.listen(8080, () => {
  console.log("Server started!")
})

封裝上下文對(duì)象
為了實(shí)現(xiàn)類似 Koa 那種 ctx.xxx 這樣的方式,先來新建3個(gè)文件:request.js,response.js,context.js 。

// request.js  以 url 為例:

const request = {
  get url () {
    return this.req.url
  }
}
module.exports = request
// response.js

const reponse = {
  get body () {
    return this._body
  },
  set body (val) {
    this._body = val
  }
}

module.exports = reponse
// context.js

const context = {
  get url () {
    return this.request.url
  },
  get body () {
  return this.response.body
  },
  set body (val) {
    this.response.body = val
  }
}

module.exports = context
    

整合上下文對(duì)象到服務(wù)類
可能看到上面3個(gè)對(duì)象,會(huì)有點(diǎn)迷糊的感覺,下面就把這3個(gè)對(duì)象添加到 Application 類中:

const http = require("http")
const request = require("./require.js")
const response = require("./response.js")
const context = require("./context.js")

class Application {
  constructor () {
  // 先把這3個(gè)屬性添加到構(gòu)造函數(shù)中
    this.context = context
    this.request = request
    this.response = response
  }
  use (cb) {
    this.callback = cb
  }
  createCtx (req, res) {
  // 新建 ctx 對(duì)象,并且繼承于 context
    const ctx = Object.create(this.context)
  // 像 ctx 對(duì)象添加兩個(gè)屬性 request  response
    ctx.request = Object.create(this.request)
    ctx.response = Object.create(this.response)
    // 像 ctx 添加 req res 屬性,同時(shí)掛載到 response request 對(duì)象上
    // req res 為 nodejs http 模塊的 原生對(duì)象
    ctx.req = ctx.request.req = req
    ctx.res = ctx.response.res = res
    return ctx
  }
  listen (...args) {
  // 這里改造成 異步形式
    const server = http.createServer(async (req, res) => {
      const ctx = this.createCtx(req, res)
      await this.callback(ctx)
      ctx.res.end(ctx.body)
    })
    server.listen(...args)
  }
}

module.exports = Application

修改 server.js 文件,再次測(cè)試:

const Koa = require("./application.js")
const app = new Koa()

app.use(async (ctx) => {
ctx.body = ctx.url
})

app.listen(8080, () => {
console.log("Server started!")
})
串聯(lián)中間件
到此為止,咱們寫的 Koa 只能使用一個(gè)中間件,而且還不涉及到異步,下面咱們就一起來看看 Koa 中最核心的 compose 函數(shù),是如何把各個(gè)中間件串聯(lián)起來的。

為了更容易的理解,先來寫一個(gè)同步版本的,依次執(zhí)行 fn1, fn2:

const fn1 = x => Math.pow(x, 2)
const fn2 = x => 2 * x

function compose (middlewares) {
  return (x) => {
    let ret = middlewares[0](x)
 for (let i=1; i

上面代碼可以直接在瀏覽器中測(cè)試結(jié)果。

那么如果 fn1 fn2 中如果有異步操作,應(yīng)該如何處理呢,實(shí)際上只需要使用 Promise 改造一下 compose 的邏輯即可。

首先實(shí)現(xiàn)一個(gè)測(cè)試用休眠函數(shù):

const sleep = (duratioin = 2000) => new Promise((resolve) => {
  setTimeout(resolve, duratioin)
})

其次準(zhǔn)備3個(gè)測(cè)試用異步函數(shù),最終效果是實(shí)現(xiàn)一個(gè)洋蔥圈模型:

const fn1 = async (next) => {
  console.log("fn1 start 休眠2秒")
  await sleep()
  await next()
  console.log("fn1 over")
}

const fn2 = async (next) => {
  console.log("fn2 start 休眠3秒")
  await sleep(3000)
  await next()
  console.log("fn2 duration....")
  await sleep(1000)
  console.log("fn2 over")
}

const fn3= async (next) => {
  console.log("fn3 start")
  await sleep()
  console.log("fn3 over")
}

執(zhí)行的順序?yàn)?fn1 > fn2 > fn3 > fn2 > fn1
最后就是主角 componse

function compose (middlewares) {
  return (context) => {
    return dispatch(0)
    function dispatch (i) {
      const fn = middlewares[i]
      if (!fn) return Promise.resolve()
      return Promise.resolve(fn(function next () {
              // await 的本質(zhì)就是 一個(gè)返回 Promise 
                 對(duì)象的函數(shù)
              // 所以這里一定要 return
        return dispatch(i+1)
      }))
    }
  }
}

測(cè)試用例:

const fn = compose([fn1, fn2, fn3])
fn()

效果如下圖:

整合compose到Server
廢話不說,直接上代碼:

class Application {
  constructor () {
    this.context = context
    this.request = request
    this.response = response
    this.middlewares = []
  }
  use (middleware) {
    this.middlewares.push(middleware)
    return this
  }
  createCtx (req, res) {
    const ctx = Object.create(this.context)
    ctx.request = Object.create(this.request)
    ctx.response = Object.create(this.response)
    ctx.req = ctx.request.req = req
    ctx.res = ctx.response.res = res
    return ctx
  }
  compose (middlewares) {
    return ctx => {
      return dispatch(0)
      function dispatch (index) {
        const fn = middlewares[index++]
        if (!fn || typeof fn !== "function") {
    return Promise.resolve()
  }
        return Promise.resolve(fn(ctx, next))
        function next () {
          return dispatch(index)
        }
      }
    }
  }
  listen (...rest) {
    const server = http.createServer(async (req, res) => {
      const ctx = this.createCtx(req, res)
      const fn = this.compose(this.middlewares)
      await fn(ctx) 
      
      ctx.res.end(ctx.body)
    })
    server.listen(...rest)
  }
}

module.exports = Application

下面可以測(cè)試一下了~

const Koa = require("./application.js")
const app = new Koa()

const sleep = (time) => new Promise((resolve, reject) => {
  setTimeout(resolve, time || 2000)
})

app.use(async (ctx, next) => {
  ctx.body = "Hello"
  await sleep()
  await next()
  ctx.body += "q!"
})

app.use(async (ctx, next) => {
  ctx.body += ", My name is"
  await sleep()
  await next()
})

app.use(async (ctx, next) => {
  ctx.body += " F"
})

app.listen(8080, () => {
  console.log("Server started!")
})

——到此為止,一個(gè)簡(jiǎn)單的 Koa 就實(shí)現(xiàn)完畢了,是不是 so easy ?

——以上是筆者歸納總結(jié),如有誤之處,歡迎指出。

原創(chuàng): 付強(qiáng) 想要關(guān)注更多作者文章可關(guān)注:微信訂閱號(hào)ID:Miaovclass

微信訂閱號(hào)“妙味前端”,為您帶來優(yōu)質(zhì)前端技術(shù)干貨;

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/53131.html

相關(guān)文章

  • 漫談Nuclear Web組件化入門篇

    摘要:目前來看,團(tuán)隊(duì)內(nèi)部前端項(xiàng)目已全面實(shí)施組件化開發(fā)。層疊樣式保佑不要污染別的在前端,一般一個(gè)組件必須要有骨架和裝飾的以及邏輯。事件綁定條件判斷秒后改變,會(huì)自動(dòng)變更。循環(huán)姓名年齡增加修改移除的變更也能監(jiān)聽到,能夠自動(dòng)觸發(fā)的變更。 目前來看,團(tuán)隊(duì)內(nèi)部前端項(xiàng)目已全面實(shí)施組件化開發(fā)。組件化的好處太多,如:按需加載、可復(fù)用、易維護(hù)、可擴(kuò)展、少挖坑、不改組件代碼直接切成服務(wù)器端渲染(如Nuclear組...

    VPointer 評(píng)論0 收藏0
  • Web框架常用架構(gòu)模式(JavaScript語(yǔ)言)

    摘要:只能在不同的時(shí)候選用不同的假設(shè)和不同的理論來解釋問題,許來西的文章講到科學(xué)一定程度上通過放棄一貫性換取了實(shí)用性,放棄自洽性換取了它洽性。然而遺憾的是本身只提供了模塊和洋蔥模型的最小封裝。 在寫干貨之前,我想先探(qiang)討(diao)兩個(gè)問題,模式的局限性?模式有什么用? 最近看到一篇文章對(duì)我啟發(fā)很大,許來西在知乎的回答《哲學(xué)和科學(xué)有什么關(guān)聯(lián)?》,全篇較長(zhǎng),這里摘錄我要引出的一點(diǎn):...

    loostudy 評(píng)論0 收藏0
  • 你不能不知道Koa實(shí)現(xiàn)原理

    摘要:前言什么這是一篇源碼解讀文章那一定很枯燥不看。通過利用函數(shù),幫你丟棄回調(diào)函數(shù),并有力地增強(qiáng)錯(cuò)誤處理。并沒有捆綁任何中間件,而是提供了一套優(yōu)雅的方法,幫助您快速而愉快地編寫服務(wù)端應(yīng)用程序。 showImg(https://segmentfault.com/img/bVNQYf?w=1020&h=790); 前言 什么?這是一篇源碼解讀文章 ? 那一定很枯燥!不看。 我把 Koa 的核心實(shí)...

    LinkedME2016 評(píng)論0 收藏0
  • koa2開發(fā)微信公眾號(hào): 不定期推送最新幣圈消息

    摘要:背景比特幣說好的分叉最后卻分叉不成,如今算力又不夠,于是比特現(xiàn)金想篡位沒一個(gè)星期就漲了快倍,錯(cuò)過這趟快車甚是后悔,于是打算寫一個(gè)可不定期推送最新消息的微信公眾號(hào)。既然是利用微信這個(gè)平臺(tái)載體,當(dāng)然要熟悉微信的,遂封裝了一下。 背景:比特幣說好的segwit2x分叉最后卻分叉不成,如今算力又不夠,于是比特現(xiàn)金想篡位? 沒一個(gè)星期就漲了快10倍,錯(cuò)過這趟快車甚是后悔,于是打算寫一個(gè)可不定期推...

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

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

0條評(píng)論

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