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

資訊專欄INFORMATION COLUMN

iKcamp|基于Koa2搭建Node.js實(shí)戰(zhàn)(含視頻)? 錯(cuò)誤處理

leeon / 1022人閱讀

滬江CCtalk視頻地址:https://www.cctalk.com/v/15114923887518

處理錯(cuò)誤請求
愛能遮掩一切過錯(cuò)。

當(dāng)我們在訪問一個(gè)站點(diǎn)的時(shí)候,如果訪問的地址不存在(404),或服務(wù)器內(nèi)部發(fā)生了錯(cuò)誤(500),站點(diǎn)會(huì)展示出某個(gè)特定的頁面,比如:

那么如何在 Koa 中實(shí)現(xiàn)這種功能呢?其實(shí),一個(gè)簡單的中間件即可實(shí)現(xiàn),我們把它稱為 http-error。實(shí)現(xiàn)過程并不復(fù)雜,拆分為三步來看:

第一步:確認(rèn)需求

第二步:整理思路

第三步:代碼實(shí)現(xiàn)


確認(rèn)需求
打造一個(gè)事物前,需要先確認(rèn)它具有什么特性,這就是需求。


在這里,稍微整理下即可得到幾個(gè)基本需求:

在頁面請求出現(xiàn) 400 、 500 類錯(cuò)誤碼的時(shí)候,引導(dǎo)用戶至錯(cuò)誤頁面;

提供默認(rèn)錯(cuò)誤頁面;

允許使用者自定義錯(cuò)誤頁面。


整理思路

現(xiàn)在,從一個(gè)請求進(jìn)入 Koa 開始說起:

一個(gè)請求訪問 Koa,出現(xiàn)了錯(cuò)誤;

該錯(cuò)誤會(huì)被 http-error 中間件捕捉到;

錯(cuò)誤會(huì)被中間件的錯(cuò)誤處理邏輯捕捉到,并進(jìn)行處理;

錯(cuò)誤處理邏輯根據(jù)錯(cuò)誤碼狀態(tài),調(diào)用渲染頁面邏輯;

渲染頁面邏輯渲染出對應(yīng)的錯(cuò)誤頁面。

可以看到,關(guān)鍵點(diǎn)就是捕捉錯(cuò)誤,以及實(shí)現(xiàn)錯(cuò)誤處理邏輯和渲染頁面邏輯。


代碼實(shí)現(xiàn) 建立文件

基于教程目錄結(jié)構(gòu),我們創(chuàng)建 middleware/mi-http-error/index.js 文件,存放中間件的邏輯代碼。初始目錄結(jié)構(gòu)如下:

middleware/
├─ mi-http-error/
│  └── index.js
└─ index.js

注意: 目錄結(jié)構(gòu)不存在,需要自己創(chuàng)建。


捕捉錯(cuò)誤

該中間件第一項(xiàng)需要實(shí)現(xiàn)的功能是捕捉到所有的 http 錯(cuò)誤。根據(jù)中間件的洋蔥模型,需要做幾件事:

1. 引入中間件

修改 middleware/index.js,引入 mi-http-error 中間件,并將它放到洋蔥模型的最外層

const path = require("path")
const ip = require("ip")
const bodyParser = require("koa-bodyparser")
const nunjucks = require("koa-nunjucks-2")
const staticFiles = require("koa-static")
const miSend = require("./mi-send")
const miLog = require("./mi-log")

// 引入請求錯(cuò)誤中間件
const miHttpError = require("./mi-http-error")
module.exports = (app) => {
  // 應(yīng)用請求錯(cuò)誤中間件
  app.use(miHttpError())
  app.use(miLog(app.env, {
    env: app.env,
    projectName: "koa2-tutorial",
    appLogLevel: "debug",
    dir: "logs",
    serverIp: ip.address()
  }));
  app.use(staticFiles(path.resolve(__dirname, "../public")))
  app.use(nunjucks({
    ext: "html",
    path: path.join(__dirname, "../views"),
    nunjucksConfig: {
      trimBlocks: true
    }
  }));
  app.use(bodyParser())
  app.use(miSend())
}
2. 捕獲中間件異常情況

修改 mi-http-error/index.js,在中間件內(nèi)部對內(nèi)層的其它中間件進(jìn)行錯(cuò)誤監(jiān)聽,并對捕獲 catch 到的錯(cuò)誤進(jìn)行處理

module.exports = () => {
  return async (ctx, next) => {
    try {
       await next();
       /**
        * 如果沒有更改過 response 的 status,則 koa 默認(rèn)的 status 是 404 
        */
       if (ctx.response.status === 404 && !ctx.response.body) ctx.throw(404);
    } catch (e) {
      /*此處進(jìn)行錯(cuò)誤處理,下面會(huì)講解具體實(shí)現(xiàn)*/
    }
  }
}


上面的準(zhǔn)備工作做完,下面實(shí)現(xiàn)兩個(gè)關(guān)鍵邏輯。


錯(cuò)誤處理邏輯

錯(cuò)誤處理邏輯其實(shí)很簡單,就是對錯(cuò)誤碼進(jìn)行判斷,并指定要渲染的文件名。這段代碼運(yùn)行在錯(cuò)誤 catch 中。

修改 mi-http-error/index.js

module.exports = () => {
  let fileName = "other"
  return async (ctx, next) => {
    try {
       await next();
       /**
        * 如果沒有更改過 response 的 status,則 koa 默認(rèn)的 status 是 404 
        */
       if (ctx.response.status === 404 && !ctx.response.body) ctx.throw(404);
    } catch (e) {
      let status = parseInt(e.status)
      // 默認(rèn)錯(cuò)誤信息為 error 對象上攜帶的 message
      const message = e.message

      // 對 status 進(jìn)行處理,指定錯(cuò)誤頁面文件名 
      if(status >= 400){
        switch(status){
          case 400:
          case 404:
          case 500:
            fileName = status;
            break;
          // 其它錯(cuò)誤 指定渲染 other 文件
          default:
            fileName = "other"
        }
      }
    }
  }
}

也就是說,對于不同的情況,會(huì)展示不同的錯(cuò)誤頁面:

├─ 400.html
├─ 404.html
├─ 500.html
├─ other.html

這幾個(gè)頁面文件我們會(huì)在后面創(chuàng)建,接下來我們開始講述下頁面渲染的問題。


渲染頁面邏輯

首先我們創(chuàng)建默認(rèn)的錯(cuò)誤頁面模板文件 mi-http-error/error.html,這里采用 nunjucks 語法。




  Error - {{ status }}


  

Error - {{ status }}

Looks like something broke!

{% if (env === "development") %}

Message:

      
        {{ error }}
      
    

Stack:

      
        {{ stack }}
      
    
{% endif %}


因?yàn)闋可娴轿募窂降慕馕?,我們需要引?path 模塊。另外,還需要引入 nunjucks 工具來解析模板。pathnode 模塊,我們只需從 npm 上安裝nunjucks 即可。


安裝 nunjucks 模塊來解析模板文件:

npm i nunjucks -S


修改 mi-http-error/index.js,引入 pathnunjucks 模塊:

// 引入 path nunjucks 模塊 
const Path = require("path") 
const nunjucks = require("nunjucks")

module.exports = () => {
  // 此處代碼省略,與之前一樣
}


為了支持自定義錯(cuò)誤文件目錄,原來調(diào)用中間件的代碼需要修改一下。我們給中間件傳入一個(gè)配置對象,該對象中有一個(gè)字段 errorPageFolder,表示自定義錯(cuò)誤文件目錄。

修改 middleware/index.js

// app.use(miHttpError())
app.use(miHttpError({
  errorPageFolder: path.resolve(__dirname, "../errorPage")
}))

注意: 代碼中,我們指定了 /errorPage 為默認(rèn)的模板文件目錄。


修改 mi-http-error/index.js,處理接收到的參數(shù):

const Path = require("path") 
const nunjucks = require("nunjucks")

module.exports = (opts = {}) => {
  // 400.html 404.html other.html 的存放位置
  const folder = opts.errorPageFolder
  // 指定默認(rèn)模板文件
  const templatePath = Path.resolve(__dirname, "./error.html") 

  let fileName = "other"
  return async (ctx, next) => {
    try {
       await next()
       if (ctx.response.status === 404 && !ctx.response.body) ctx.throw(404);
    } catch (e) {
      let status = parseInt(e.status)
      const message = e.message
      if(status >= 400){
        switch(status){
          case 400:
          case 404:
          case 500:
            fileName = status;
            break;
          default:
            fileName = "other"
        }
      }else{// 其它情況,統(tǒng)一返回為 500
        status = 500
        fileName = status
      }
      // 確定最終的 filePath 路徑
      const filePath = folder ? Path.join(folder, `${fileName}.html`) : templatePath
    }
  }
}


路徑和參數(shù)準(zhǔn)備好之后,我們需要做的事情就剩返回渲染的頁面了。


修改 mi-http-error/index.js,對捕捉到的不同錯(cuò)誤返回相應(yīng)的視圖頁面:

const Path = require("path") 
const nunjucks = require("nunjucks")
module.exports = (opts = {}) => {
  // 增加環(huán)境變量,用來傳入到視圖中,方便調(diào)試
  const env = opts.env || process.env.NODE_ENV || "development"  

  const folder = opts.errorPageFolder
  const templatePath = Path.resolve(__dirname, "./error.html")
  let fileName = "other"
  return async (ctx, next) => {
    try {
       await next()
       if (ctx.response.status === 404 && !ctx.response.body) ctx.throw(404);
    } catch (e) {
      let status = parseInt(e.status)
      const message = e.message
      if(status >= 400){
        switch(status){
          case 400:
          case 404:
          case 500:
            fileName = status;
            break;
          default:
            fileName = "other"
        }
      }else{
        status = 500
        fileName = status
      }
      const filePath = folder ? Path.join(folder, `${fileName}.html`) : templatePath
      
      // 渲染對應(yīng)錯(cuò)誤類型的視圖,并傳入?yún)?shù)對象
      try{
        // 指定視圖目錄
        nunjucks.configure( folder ? folder : __dirname )
        const data = await nunjucks.render(filePath, {
          env: env, // 指定當(dāng)前環(huán)境參數(shù)
          status: e.status || e.message, // 如果錯(cuò)誤信息中沒有 status,就顯示為 message
          error: e.message, // 錯(cuò)誤信息
          stack: e.stack // 錯(cuò)誤的堆棧信息
        })
        // 賦值給響應(yīng)體
        ctx.status = status
        ctx.body = data
      }catch(e){
        // 如果中間件存在錯(cuò)誤異常,直接拋出信息,由其他中間件處理
        ctx.throw(500, `錯(cuò)誤頁渲染失敗:${e.message}`)
      }
    }
  }
}

上面所做的是使用渲染引擎對模板文件進(jìn)行渲染,并將生成的內(nèi)容放到 HttpResponse 中,展示在用戶面前。感興趣的同學(xué)可以去中間件源碼中查看 error.html 查看模板內(nèi)容(其實(shí)是從 koa-error 那里拿來稍作修改的)。


在代碼的最后,我們還有一個(gè)異常的拋出 ctx.throw(),也就是說,中間件處理時(shí)候也會(huì)存在異常,所以我們需要在最外層做一個(gè)錯(cuò)誤監(jiān)聽處理。

修改 middleware/index.js

const path = require("path")
const ip = require("ip")
const bodyParser = require("koa-bodyparser")
const nunjucks = require("koa-nunjucks-2")
const staticFiles = require("koa-static")

const miSend = require("./mi-send")
const miLog = require("./mi-log")
const miHttpError = require("./mi-http-error")
module.exports = (app) => {
  app.use(miHttpError({
    errorPageFolder: path.resolve(__dirname, "../errorPage")
  }))

  app.use(miLog(app.env, {
    env: app.env,
    projectName: "koa2-tutorial",
    appLogLevel: "debug",
    dir: "logs",
    serverIp: ip.address()
  }));

  app.use(staticFiles(path.resolve(__dirname, "../public")))

  app.use(nunjucks({
    ext: "html",
    path: path.join(__dirname, "../views"),
    nunjucksConfig: {
      trimBlocks: true
    }
  }));

  app.use(bodyParser())
  app.use(miSend())

  // 增加錯(cuò)誤的監(jiān)聽處理
  app.on("error", (err, ctx) => {
    if (ctx && !ctx.headerSent && ctx.status < 500) {
      ctx.status = 500
    }
    if (ctx && ctx.log && ctx.log.error) {
      if (!ctx.state.logged) {
        ctx.log.error(err.stack)
      }
    }
  }) 
}


下面,我們增加對應(yīng)的錯(cuò)誤渲染頁面:

創(chuàng)建 errorPage/400.html




  400


  

Error - {{ status }}

錯(cuò)誤碼 400 的描述信息

{% if (env === "development") %}

Message:

      
        {{ error }}
      
    

Stack:

      
        {{ stack }}
      
    
{% endif %}


創(chuàng)建 errorPage/404.html




  404


  

Error - {{ status }}

錯(cuò)誤碼 404 的描述信息

{% if (env === "development") %}

Message:

      
        {{ error }}
      
    

Stack:

      
        {{ stack }}
      
    
{% endif %}


創(chuàng)建 errorPage/500.html




  500


  

Error - {{ status }}

錯(cuò)誤碼 500 的描述信息

{% if (env === "development") %}

Message:

      
        {{ error }}
      
    

Stack:

      
        {{ stack }}
      
    
{% endif %}


創(chuàng)建 errorPage/other.html




  未知異常


  

Error - {{ status }}

未知異常

{% if (env === "development") %}

Message:

      
        {{ error }}
      
    

Stack:

      
        {{ stack }}
      
    
{% endif %}


errorPage 中的頁面展示內(nèi)容,可以根據(jù)自己的項(xiàng)目信息修改,以上僅供參考。


至此,我們基本完成了用來處理『請求錯(cuò)誤』的中間件。而這個(gè)中間件并不是固定的形態(tài),大家在真實(shí)項(xiàng)目中,還需要多考慮自己的業(yè)務(wù)場景和需求,打造出適合自己項(xiàng)目的中間件。

下一節(jié)中,我們將學(xué)習(xí)下規(guī)范與部署——制定合適的團(tuán)隊(duì)規(guī)范,提升開發(fā)效率。

上一篇:iKcamp新課程推出啦~~~~~iKcamp|基于Koa2搭建Node.js實(shí)戰(zhàn)(含視頻)? 處理靜態(tài)資源
推薦: 翻譯項(xiàng)目Master的自述: 1. 干貨|人人都是翻譯項(xiàng)目的Master 2. iKcamp出品微信小程序教學(xué)共5章16小節(jié)匯總(含視頻)

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

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

相關(guān)文章

  • 開始連載啦~每周2更共11堂iKcamp課|基于Koa2搭建Node.js實(shí)戰(zhàn)項(xiàng)目教學(xué)(視頻)|

    摘要:玩轉(zhuǎn)同時(shí)全面掌握潮流技術(shù)采用新一代的開發(fā)框架更小更富有表現(xiàn)力更健壯。融合多種常見的需求場景網(wǎng)絡(luò)請求解析模板引擎靜態(tài)資源日志記錄錯(cuò)誤請求處理。結(jié)合語句中轉(zhuǎn)中間件控制權(quán),解決回調(diào)地獄問題。注意分支中的目錄為當(dāng)節(jié)課程后的完整代碼。 ?? ?與眾不同的學(xué)習(xí)方式,為你打開新的編程視角 獨(dú)特的『同步學(xué)習(xí)』方式 文案講解+視頻演示,文字可激發(fā)深層的思考、視頻可還原實(shí)戰(zhàn)操作過程。 云集一線大廠...

    B0B0 評論0 收藏0
  • 【完結(jié)匯總】iKcamp出品基于Koa2搭建Node.js實(shí)戰(zhàn)共十一堂課(視頻)

    摘要:云集一線大廠有真正實(shí)力的程序員團(tuán)隊(duì)云集一線大廠經(jīng)驗(yàn)豐厚的碼農(nóng),開源奉獻(xiàn)各教程。融合多種常見的需求場景網(wǎng)絡(luò)請求解析模板引擎靜態(tài)資源日志記錄錯(cuò)誤請求處理。結(jié)合語句中轉(zhuǎn)中間件控制權(quán),解決回調(diào)地獄問題。注意分支中的目錄為當(dāng)節(jié)課程后的完整代碼。 ?? ?與眾不同的學(xué)習(xí)方式,為你打開新的編程視角 獨(dú)特的『同步學(xué)習(xí)』方式 文案講解+視頻演示,文字可激發(fā)深層的思考、視頻可還原實(shí)戰(zhàn)操作過程。 云...

    sPeng 評論0 收藏0
  • iKcamp基于Koa2搭建Node.js實(shí)戰(zhàn)視頻)? 代碼分層

    視頻地址:https://www.cctalk.com/v/15114923889408 showImg(https://segmentfault.com/img/remote/1460000012682164?w=1604&h=964); 文章 在前面幾節(jié)中,我們已經(jīng)實(shí)現(xiàn)了項(xiàng)目中的幾個(gè)常見操作:啟動(dòng)服務(wù)器、路由中間件、Get 和 Post 形式的請求處理等?,F(xiàn)在你已經(jīng)邁出了走向成功的第一步。 ...

    shusen 評論0 收藏0
  • iKcamp基于Koa2搭建Node.js實(shí)戰(zhàn)視頻)? HTTP請求

    POST/GET請求——常見請求方式處理 ?? iKcamp 制作團(tuán)隊(duì) 原創(chuàng)作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校對:李益、大力萌、Au、DDU、小溪里、小哈 風(fēng)采主播:可木、阿干、Au、DDU、小哈 視頻剪輯:小溪里 主站運(yùn)營:給力xi、xty 教程主編:張利濤 視頻地址:https://www.cctalk.com/v/15114357765870 ...

    張利勇 評論0 收藏0
  • iKcamp基于Koa2搭建Node.js實(shí)戰(zhàn)視頻)? 解析JSON

    視頻地址:https://www.cctalk.com/v/15114923886141 showImg(https://segmentfault.com/img/remote/1460000012840997?w=1604&h=964); JSON 數(shù)據(jù) 我顛倒了整個(gè)世界,只為擺正你的倒影。 前面的文章中,我們已經(jīng)完成了項(xiàng)目中常見的問題,比如 路由請求、結(jié)構(gòu)分層、視圖渲染、靜態(tài)資源等。 那么,J...

    mudiyouyou 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<