欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解KOA2如何手寫中間件(裝飾器模式)

 更新時間:2018年10月11日 14:59:59   作者:煎蛋面__cq  
這篇文章主要介紹了詳解KOA2如何手寫中間件(裝飾器模式),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

Koa 2.x 版本是當下最流行的 NodeJS 框架, Koa 2.0 的源碼特別精簡,不像 Express 封裝的功能那么多,所以大部分的功能都是由 Koa 開發(fā)團隊(同 Express 是一家出品)和社區(qū)貢獻者針對 Koa 對 NodeJS 的封裝特性實現(xiàn)的中間件來提供的,用法非常簡單,就是引入中間件,并調(diào)用 Koa 的 use 方法使用在對應的位置,這樣就可以通過在內(nèi)部操作 ctx 實現(xiàn)一些功能,我們接下來就討論常用中間件的實現(xiàn)原理以及我們應該如何開發(fā)一個 Koa 中間件供自己和別人使用。

Koa 的洋蔥模型介紹

我們本次不對洋蔥模型的實現(xiàn)原理進行過多的刨析,主要根據(jù) API 的使用方式及洋蔥模型分析中間件是如何工作的。

洋蔥模型特點

// 引入 Koa
const Koa = require("koa");

// 創(chuàng)建服務
const app = new Koa();

app.use(async (ctx, next) => {
  console.log(1);
  await next();
  console.log(2);
});

app.use(async (ctx, next) => {
  console.log(3);
  await next();
  console.log(4);
});

app.use(async (ctx, next) => {
  console.log(5);
  await next();
  console.log(6);
});

// 監(jiān)聽服務
app.listen(3000);

// 1
// 3
// 5
// 6
// 4
// 2

我們知道 Koa 的 use 方法是支持異步的,所以為了保證正常的按照洋蔥模型的執(zhí)行順序執(zhí)行代碼,需要在調(diào)用 next 的時候讓代碼等待,等待異步結束后再繼續(xù)向下執(zhí)行,所以我們在 Koa 中都是建議使用 async/await 的,引入的中間件都是在 use 方法中調(diào)用,由此我們可以分析出每一個 Koa 的中間件都是返回一個 async 函數(shù)的。

koa-bodyparser 中間件模擬

想要分析 koa-bodyparser 的原理首先需要知道用法和作用, koa-bodyparser 中間件是將我們的 post 請求和表單提交的查詢字符串轉換成對象,并掛在 ctx.request.body 上,方便我們在其他中間件或接口處取值,使用前需提前安裝。

npm install koa koa-bodyparser

koa-bodyparser 具體用法如下:

koa-bodyparser 的用法

const Koa = require("koa");
const bodyParser = require("koa-bodyparser");

const app = new Koa();

// 使用中間件
app.use(bodyParser());

app.use(async (ctx, next) => {
  if (ctx.path === "/" && ctx.method === "POST") {
    // 使用中間件后 ctx.request.body 屬性自動加上了 post 請求的數(shù)據(jù)
    console.log(ctx.request.body);
  }
});

app.listen(3000);

根據(jù)用法我們可以看出 koa-bodyparser 中間件引入的其實是一個函數(shù),我們把它放在了 use 中執(zhí)行,根據(jù) Koa 的特點,我們推斷出 koa-bodyparser 的函數(shù)執(zhí)行后應該給我們返回了一個 async 函數(shù),下面是我們模擬實現(xiàn)的代碼。

文件:my-koa-bodyparser.js

const querystring = require("querystring");

module.exports = function bodyParser() {
  return async (ctx, next) => {
    await new Promise((resolve, reject) => {
      // 存儲數(shù)據(jù)的數(shù)組
      let dataArr = [];

      // 接收數(shù)據(jù)
      ctx.req.on("data", data => dataArr.push(data));

      // 整合數(shù)據(jù)并使用 Promise 成功
      ctx.req.on("end", () => {
        // 獲取請求數(shù)據(jù)的類型 json 或表單
        let contentType = ctx.get("Content-Type");

        // 獲取數(shù)據(jù) Buffer 格式
        let data = Buffer.concat(dataArr).toString();

        if (contentType === "application/x-www-form-urlencoded") {
          // 如果是表單提交,則將查詢字符串轉換成對象賦值給 ctx.request.body
          ctx.request.body = querystring.parse(data);
        } else if (contentType === "applaction/json") {
          // 如果是 json,則將字符串格式的對象轉換成對象賦值給 ctx.request.body
          ctx.request.body = JSON.parse(data);
        }

        // 執(zhí)行成功的回調(diào)
        resolve();
      });
    });

    // 繼續(xù)向下執(zhí)行
    await next();
  };
};

在上面代碼中由幾點是需要我們注意的,即 next 的調(diào)用以及為什么通過流接收數(shù)據(jù)、處理數(shù)據(jù)和將數(shù)據(jù)掛在 ctx.request.body 要在 Promise 中進行。

首先是 next 的調(diào)用,我們知道 Koa 的 next 執(zhí)行,其實就是在執(zhí)行下一個中間件的函數(shù),即下一個 use 中的 async 函數(shù),為了保證后面的異步代碼執(zhí)行完畢后再繼續(xù)執(zhí)行當前的代碼,所以我們需要使用 await 進行等待,其次就是數(shù)據(jù)從接收到掛在 ctx.request.body 都在 Promise 中執(zhí)行,是因為在接收數(shù)據(jù)的操作是異步的,整個處理數(shù)據(jù)的過程需要等待異步完成后,再把數(shù)據(jù)掛在 ctx.request.body 上,可以保證我們在下一個 use 的 async 函數(shù)中可以在 ctx.request.body 上拿到數(shù)據(jù),所以我們使用 await 等待一個 Promise 成功后再執(zhí)行 next 。

koa-better-body 中間件模擬

koa-bodyparser 在處理表單提交時還是顯得有一點弱,因為不支持文件上傳,而 koa-better-body 則彌補了這個不足,但是 koa-better-body 為 Koa 1.x 版本的中間件, Koa 1.x 的中間件都是使用 Generator 函數(shù)實現(xiàn)的,我們需要使用 koa-convert 將 koa-better-body 轉化成 Koa 2.x 的中間件。

npm install koa koa-better-body koa-convert path uuid

koa-better-body 具體用法如下:

koa-better-body 的用法

const Koa = require("koa");
const betterBody = require("koa-better-body");
const convert = require("koa-convert"); // 將 koa 1.0 中間轉化成 koa 2.0 中間件
const path = require("path");
const fs = require("fs");
const uuid = require("uuid/v1"); // 生成隨機串

const app = new Koa();

// 將 koa-better-body 中間件從 koa 1.0 轉化成 koa 2.0,并使用中間件
app.use(convert(betterBody({
  uploadDir: path.resolve(__dirname, "upload")
})));

app.use(async (ctx, next) => {
  if (ctx.path === "/" && ctx.method === "POST") {
    // 使用中間件后 ctx.request.fields 屬性自動加上了 post 請求的文件數(shù)據(jù)
    console.log(ctx.request.fields);

    // 將文件重命名
    let imgPath = ctx.request.fields.avatar[0].path;
    let newPath = path.resolve(__dirname, uuid());
    fs.rename(imgPath, newPath);
  }
});

app.listen(3000);

上面代碼中 koa-better-body 的主要功能就是將表單上傳的文件存入本地指定的文件夾下,并將文件流對象掛在了 ctx.request.fields 屬性上,我們接下來就模擬 koa-better-body 的功能實現(xiàn)一版基于 Koa 2.x 處理文件上傳的中間件。

文件:my-koa-better-body.js

const fs = require("fs");
const uuid = require("uuid/v1");
const path = require("path");

// 給 Buffer 擴展 split 方法預備后面使用
Buffer.prototype.split = function (sep) {
  let len = Buffer.from(sep).length; // 分隔符所占的字節(jié)數(shù)
  let result = []; // 返回的數(shù)組
  let start = 0; // 查找 Buffer 的起始位置
  let offset = 0; // 偏移量

  // 循環(huán)查找分隔符
  while ((offset = this.indexOf(sep, start)) !== -1) {
    // 將分隔符之前的部分截取出來存入
    result.push(this.slice(start, offset));
    start = offset + len;
  }

  // 處理剩下的部分
  result.push(this.slice(start));

  // 返回結果
  return result;
}

module.exports = function (options) {
  return async (ctx, next) => {
    await new Promise((resolve, reject) => {
      let dataArr = []; // 存儲讀取的數(shù)據(jù)

      // 讀取數(shù)據(jù)
      ctx.req.on("data", data => dataArr.push(data));

      ctx.req.on("end", () => {
        // 取到請求體每段的分割線字符串
        let bondery = `--${ctx.get("content-Type").split("=")[1]}`;

        // 獲取不同系統(tǒng)的換行符
        let lineBreak = process.platform === "win32" ? "\r\n" : "\n";

        // 非文件類型數(shù)據(jù)的最終返回結果
        let fields = {};

        // 分隔的 buffer 去掉沒用的頭和尾即開頭的 '' 和末尾的 '--'
        dataArr = dataArr.split(bondery).slice(1, -1);

        // 循環(huán)處理 dataArr 中每一段 Buffer 的內(nèi)容
        dataArr.forEach(lines => {
          // 對于普通值,信息由包含鍵名的行 + 兩個換行 + 數(shù)據(jù)值 + 換行組成
          // 對于文件,信息由包含 filename 的行 + 兩個換行 + 文件內(nèi)容 + 換行組成
          let [head, tail] = lines.split(`${lineBreak}${lineBreak}`);

          // 判斷是否是文件,如果是文件則創(chuàng)建文件并寫入,如果是普通值則存入 fields 對象中
          if (head.includes("filename")) {
            // 防止文件內(nèi)容含有換行而被分割,應重新截取內(nèi)容并去掉最后的換行
            let tail = lines.slice(head.length + 2 * lineBreak.length, -lineBreak.length);

            // 創(chuàng)建可寫流并指定寫入的路徑:絕對路徑 + 指定文件夾 + 隨機文件名,最后寫入文件
            fs.createWriteStream(path.join(__dirname, options.uploadDir, uuid())).end(tail);
          } else {
            // 是普通值取出鍵名
            let key = head.match(/name="(\w+)"/)[1];

            // 將 key 設置給 fields tail 去掉末尾換行后的內(nèi)容
            fields[key] = tail.toString("utf8").slice(0, -lineBreak.length);
          }
        });

        // 將處理好的 fields 對象掛在 ctx.request.fields 上,并完成 Promise
        ctx.request.fields = fields;
        resolve();
      });
    });

    // 向下執(zhí)行
    await next();
  }
}

上面的內(nèi)容邏輯可以通過代碼注釋來理解,就是模擬 koa-better-body 的功能邏輯,我們主要的關心點在于中間件實現(xiàn)的方式,上面功能實現(xiàn)的異步操作依然是讀取數(shù)據(jù),為了等待數(shù)據(jù)處理結束仍然在 Promise 中執(zhí)行,并使用 await 等待,Promise 執(zhí)行成功調(diào)用 next 。

koa-views 中間件模擬

Node 模板是我們經(jīng)常使用的工具用來在服務端幫我們渲染頁面,模板的種類繁多,因此出現(xiàn)了 koa-view 中間件,幫我們來兼容這些模板,先安裝依賴的模塊。

npm install koa koa-views ejs

下面是一個 ejs 的模板文件:

文件:index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>ejs</title>
</head>
<body>
  <%=name%>
  <%=age%>

  <%if (name=="panda") {%>
    panda
  <%} else {%>
    shen
  <%}%>

  <%arr.forEach(item => {%>
    <li><%=item%></li>
  <%})%>
</body>
</html>

koa-views 具體用法如下:

koa-views 的用法

const Koa = require("koa");
const views = require("koa-views");
const path = require("path");

const app = new Koa();

// 使用中間件
app.use(views(path.resolve(__dirname, "views"), {
  extension: "ejs"
}));

app.use(async (ctx, next) => {
  await ctx.render("index", { name: "panda", age: 20, arr: [1, 2, 3] });
});

app.listen(3000);

可以看出我們使用了 koa-views 中間件后,讓 ctx 上多了 render 方法幫助我們實現(xiàn)對模板的渲染和響應頁面,就和直接使用 ejs 自帶的 render 方法一樣,并且從用法可以看出 render 方法是異步執(zhí)行的,所以需要使用 await 進行等待,接下來我們就來模擬實現(xiàn)一版簡單的 koa-views 中間件。

文件:my-koa-views.js

const fs = require("fs");
const path = require("path");
const { promisify } = require("util");

// 將讀取文件方法轉換成 Promise
const readFile = promisify(fs.radFile);

// 到處中間件
module.exports = function (dir, options) {
  return async (ctx, next) => {
    // 動態(tài)引入模板依賴模塊
    const view = require(options.extension);

    ctx.render = async (filename, data) => {
      // 異步讀取文件內(nèi)容
      let tmpl = await readFile(path.join(dir, `${filename}.${options.extension}`), "utf8");

      // 將模板渲染并返回頁面字符串
      let pageStr = view.render(tmpl, data);

      // 設置響應類型并響應頁面
      ctx.set("Content-Type", "text/html;charset=utf8");
      ctx.body = pageStr;
    }

    // 繼續(xù)向下執(zhí)行
    await next();
  }
}

掛在 ctx 上的 render 方法之所以是異步執(zhí)行的是因為內(nèi)部讀取模板文件是異步執(zhí)行的,需要等待,所以 render 方法為 async 函數(shù),在中間件內(nèi)部動態(tài)引入了我們使的用模板,如 ejs ,并在 ctx.render 內(nèi)部使用對應的 render 方法獲取替換數(shù)據(jù)后的頁面字符串,并以 html 的類型響應。

koa-static 中間件模擬

下面是 koa-static 中間件的用法,代碼使用的依賴如下,使用前需安裝。

npm install koa koa-static mime

koa-static 具體用法如下:

koa-static 的用法

const Koa = require("koa");
const static = require("koa-static");
const path = require("path");

const app = new Koa();

app.use(static(path.resolve(__dirname, "public")));

app.use(async (ctx, next) => {
  ctx.body = "hello world";
});

app.listen(3000);

通過使用和分析,我們知道了 koa-static 中間件的作用是在服務器接到請求時,幫我們處理靜態(tài)文件,如果我們直接訪問文件名的時候,會查找這個文件并直接響應,如果沒有這個文件路徑會當作文件夾,并查找文件夾下的 index.html ,如果存在則直接響應,如果不存在則交給其他中間件處理。

文件:my-koa-static.js

const fs = require("fs");
const path = require("path");
const mime = require("mime");
const { promisify } = require("util");

// 將 stat 和 access 轉換成 Promise
const stat = promisify(fs.stat);
const access = promisify(fs.access)

module.exports = function (dir) {
  return async (ctx, next) => {
    // 將訪問的路由處理成絕對路徑,這里要使用 join 因為有可能是 /
    let realPath = path.join(dir, ctx.path);

    try {
      // 獲取 stat 對象
      let statObj = await stat(realPath);

      // 如果是文件,則設置文件類型并直接響應內(nèi)容,否則當作文件夾尋找 index.html
      if (statObj.isFile()) {
        ctx.set("Content-Type", `${mime.getType()};charset=utf8`);
        ctx.body = fs.createReadStream(realPath);
      } else {
        let filename = path.join(realPath, "index.html");

        // 如果不存在該文件則執(zhí)行 catch 中的 next 交給其他中間件處理
        await access(filename);

        // 存在設置文件類型并響應內(nèi)容
        ctx.set("Content-Type", "text/html;charset=utf8");
        ctx.body = fs.createReadStream(filename);
      }
    } catch (e) {
      await next();
    }
  }
}

上面的邏輯中需要檢測路徑是否存在,由于我們導出的函數(shù)都是 async 函數(shù),所以我們將 stat 和 access 轉化成了 Promise,并用 try...catch 進行捕獲,在路徑不合法時調(diào)用 next 交給其他中間件處理。

koa-router 中間件模擬

在 Express 框架中,路由是被內(nèi)置在了框架內(nèi)部,而 Koa 中沒有內(nèi)置,是使用 koa-router 中間件來實現(xiàn)的,使用前需要安裝。

npm install koa koa-router

koa-router 功能非常強大,下面我們只是簡單的使用,并且根據(jù)使用的功能進行模擬。

koa-router 的簡單用法

const Koa = require("Koa");
const Router = require("koa-router");

const app = new Koa();
const router = new Router();

router.get("/panda", (ctx, next) => {
  ctx.body = "panda";
});

router.get("/panda", (ctx, next) => {
  ctx.body = "pandashen";
});

router.get("/shen", (ctx, next) => {
  ctx.body = "shen";
})

// 調(diào)用路由中間件
app.use(router.routes());

app.listen(3000);

從上面看出 koa-router 導出的是一個類,使用時需要創(chuàng)建一個實例,并且調(diào)用實例的 routes 方法將該方法返回的 async 函數(shù)進行連接,但是在匹配路由的時候,會根據(jù)路由 get 方法中的路徑進行匹配,并串行執(zhí)行內(nèi)部的回調(diào)函數(shù),當所有回調(diào)函數(shù)執(zhí)行完畢之后會執(zhí)行整個 Koa 串行的 next ,原理同其他中間件,我下面來針對上面使用的功能簡易實現(xiàn)。

文件:my-koa-router.js

// 控制每一個路由層的類
class Layer {
  constructor(path, cb) {
    this.path = path;
    this.cb = cb;
  }
  match(path) {
    // 地址的路由和當前配置路由相等返回 true,否則返回 false
    return path === this.path;
  }
}

// 路由的類
class Router {
  constructor() {
    // 存放每個路由對象的數(shù)組,{ path: /xxx, fn: cb }
    this.layers = [];
  }
  get(path, cb) {
    // 將路由對象存入數(shù)組中
    this.layers.push(new Layer(path, cb));
  }
  compose(ctx, next, handlers) {
    // 將匹配的路由函數(shù)串聯(lián)執(zhí)行
    function dispatch(index) {
      // 如果當前 index 個數(shù)大于了存儲路由對象的長度,則執(zhí)行 Koa 的 next 方法
      if(index >= handlers.length) return next();

      // 否則調(diào)用取出的路由對象的回調(diào)執(zhí)行,并傳入一個函數(shù),在傳入的函數(shù)中遞歸 dispatch(index + 1)
      // 目的是為了執(zhí)行下一個路由對象上的回調(diào)函數(shù)
      handlers[index].cb(ctx, () => dispatch(index + 1));
    }

    // 第一次執(zhí)行路由對象的回調(diào)函數(shù)
    dispatch(0);
  }
  routes() {
    return async (ctx, next) { // 當前 next 是 Koa 自己的 next,即 Koa 其他的中間件
      // 篩選出路徑相同的路由
      let handlers = this.layers.filter(layer => layer.match(ctx.path));
      this.compose(ctx, next, handlers);
    }
  }
}

在上面我們創(chuàng)建了一個 Router 類,定義了 get 方法,當然還有 post 等,我們只實現(xiàn) get 意思一下, get 內(nèi)為邏輯為將調(diào)用 get 方法的參數(shù)函數(shù)和路由字符串共同構建成對象存入了數(shù)組 layers ,所以我們創(chuàng)建了專門構造路由對象的類 Layer ,方便擴展,在路由匹配時我們可以根據(jù) ctx.path 拿到路由字符串,并通過該路由過濾調(diào)數(shù)組中與路由不匹配的路由對象,調(diào)用 compose 方法將過濾后的數(shù)組作為參數(shù) handlers 傳入,串行執(zhí)行路由對象上的回調(diào)函數(shù)。

compose 這個方法的實現(xiàn)思想非常的重要,在 Koa 源碼中用于串聯(lián)中間件,在 React 源碼中用于串聯(lián) redux 的 promise 、 thunk 和 logger 等模塊,我們的實現(xiàn)是一個簡版,并沒有兼容異步,主要思想是遞歸 dispatch 函數(shù),每次取出數(shù)組中下一個路由對象的回調(diào)函數(shù)執(zhí)行,直到所有匹配的路由的回調(diào)函數(shù)都執(zhí)行完,執(zhí)行 Koa 的下一個中間件 next ,注意此處的 next 不同于數(shù)組中回調(diào)函數(shù)的參數(shù) next ,數(shù)組中路由對象回調(diào)函數(shù)的 next 代表下一個匹配路由的回調(diào)。

總結

上面我們分析和模擬了一些中間件,其實我們會理解 Koa 和 Express 相比較的優(yōu)勢是沒有那么繁重,開發(fā)使用方便,需要的功能都可以用對應的中間件來實現(xiàn),使用中間件可以給我們帶來一些好處,比如能將我們處理好的數(shù)據(jù)和新方法掛載在 ctx 上,方便后面 use 傳入的回調(diào)函數(shù)中使用,也可以幫我們處理一些公共邏輯,不至于在每一個 use 的回調(diào)中都去處理,大大減少了冗余代碼,由此看來其實給 Koa 使用中間件的過程就是一個典型的 “裝飾器” 模式,在通過上面的分析之后相信大家也了解了 Koa 的 “洋蔥模型” 和異步特點,知道該如何開發(fā)自己的中間件了。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關文章

  • 對mac下nodejs 更新到最新版本的最新方法(推薦)

    對mac下nodejs 更新到最新版本的最新方法(推薦)

    今天小編就為大家分享一篇對mac下nodejs 更新到最新版本的最新方法(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 一文詳解Node.contain?函數(shù)兼容處理

    一文詳解Node.contain?函數(shù)兼容處理

    這篇文章主要為大家介紹了Node.contain?函數(shù)兼容處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 用Electron寫個帶界面的nodejs爬蟲的實現(xiàn)方法

    用Electron寫個帶界面的nodejs爬蟲的實現(xiàn)方法

    這篇文章主要介紹了用Electron寫個帶界面的nodejs爬蟲的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • koa+jwt實現(xiàn)token驗證與刷新功能

    koa+jwt實現(xiàn)token驗證與刷新功能

    這篇文章主要介紹了koa+jwt實現(xiàn)token驗證與刷新功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-05-05
  • Node.js處理HTTP請求的示例代碼

    Node.js處理HTTP請求的示例代碼

    Node.js是一個基于Chrome V8引擎的JavaScript運行環(huán)境,它使得JavaScript可以脫離瀏覽器在服務器端運行,Node.js的非阻塞I/O模型和事件驅動特性使其在處理HTTP請求時表現(xiàn)出色,本文將探討Node.js如何處理HTTP請求,并提供示例代碼,需要的朋友可以參考下
    2024-09-09
  • nodeJS?express路由學習req.body與req.query方法實例詳解

    nodeJS?express路由學習req.body與req.query方法實例詳解

    這篇文章主要為大家介紹了nodeJS?express路由學習req.body與req.query方法實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • node內(nèi)存泄漏排查與修復過程

    node內(nèi)存泄漏排查與修復過程

    之前開發(fā)了一個node接口,該接口使用canvas繪制產(chǎn)品圖提供給java端使用,在運行了一段時間后發(fā)現(xiàn)了內(nèi)存泄漏問題,本文淺記下修復過程,文章通過圖文介紹的非常詳細,需要的朋友可以參考下
    2024-06-06
  • Node.js中參數(shù)傳遞的兩種方式詳解

    Node.js中參數(shù)傳遞的兩種方式詳解

    這篇文章主要為大家介紹了Node.js中參數(shù)傳遞的兩種方式:GET方式和POST方式,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-04-04
  • 前端如何更好的展示后端返回的十萬條數(shù)據(jù)

    前端如何更好的展示后端返回的十萬條數(shù)據(jù)

    這篇文章主要為大家介紹了前端如何更好的展示后端返回的十萬條數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2021-11-11
  • NodeJs內(nèi)存占用過高的排查實戰(zhàn)記錄

    NodeJs內(nèi)存占用過高的排查實戰(zhàn)記錄

    這篇文章主要給大家介紹了關于NodeJs內(nèi)存占用過高的排查實戰(zhàn)記錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05

最新評論