Node.js中的異步編程的示例分析,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
10多年專業(yè)網(wǎng)絡公司歷程,堅持以創(chuàng)新為先導的網(wǎng)站服務,服務超過1000+企業(yè)及個人,涉及網(wǎng)站設計、重慶APP軟件開發(fā)、微信開發(fā)、平面設計、互聯(lián)網(wǎng)整合營銷等多個領域。在不同行業(yè)和領域給人們的工作和生活帶來美好變化。
異步編程概述
曾經(jīng)的單線程模型在同步I/O的影響下,由于I/O調用緩慢,在應用層面導致CPU與I/O無法重疊進行。為了照顧編程人員的閱讀思維習慣,同步I/O盛行了很多年。
但是有很大的性能問題!
Node利用JavaScript及其內部異步庫,將異步直接提升到業(yè)務層面。Node帶來的最大特性莫過于基于事件驅動的非阻塞I/O模型。非阻塞I/O可以使CPU與I/O并不相互依賴等待,讓資源得到更好的利用。
目的:讀取package.json 中main 字段對應的文件內容
Callback
使用回調函數(shù)進行異步I/O的操作
const fs = require("fs"); fs.readFile("./package.json", { encoding: "utf-8" }, (err, data) => { if (err) throw err; const { main } = JSON.parse(data); fs.readFile(main, { encoding: "utf-8" }, (err, data) => { if (err) throw err; console.log(data); }); });復制代碼
問題:如何解決回調地獄?
Promise
Promise是一個具有四個狀態(tài)的有限狀態(tài)機,其中三個核心狀態(tài)為Pending(掛起),F(xiàn)ulfilled( 完成)、Rejected(拒絕),以及還有一個未開始狀態(tài)
詳細內容可以看我之前的博文 Promise初探
使用Promise,實現(xiàn)讀取 package.json 中 main 字段對應的文件內容
const { readFile } = require("fs/promises"); readFile("./package.json", { encoding: "utf-8" }) .then((res) => { return JSON.parse(res); }) .then((data) => { return readFile(data.main, { encoding: "utf-8" }); }) .then((res) => { console.log(res); });復制代碼
對比之前用Callback的解決方案,可以看出沒有嵌套的回調了,通過一系列的鏈式調用來處理異步操作。
Callback 轉為 Promise
如何將 Callback 轉為 Promise 形式?
可以使用Node自帶的工具函數(shù) util.promisify
可以自己實現(xiàn)一下:
function promisify(fn, receiver) { return (...args) => { return new Promise((resolve, reject) => { fn.apply(receiver, [ ...args, (err, res) => { return err ? reject(err) : resolve(res); }, ]); }); }; }const readFilePromise = promisify(fs.readFile, fs);復制代碼
await
await 函數(shù)使用 try catch 捕獲異常(注意并行處理)
const { readFile } = require("fs/promises");const start = async () => { const { main } = JSON.parse( await readFile("./package.json", { encoding: "utf-8" }) ); const data = await readFile(main, { encoding: "utf-8" }); console.log(data); }; start();復制代碼
await的語法寫起來就像同步編程一樣,這里的操作是串行操作,會一行一行的等待執(zhí)行。
如果幾個任務是可以并行的,這樣寫就不太好了。這是,我們可以使用Promise.all來操作并行的任務
這里也會有個小問題,我課后問老師了,這是老師的解答
【問】在異步那塊,說到串行和并行,在并行處理那塊我有一個疑問。如果并行的場景要求:不管其他任務執(zhí)行成功還是失敗,每個異步任務都要執(zhí)行完,最后統(tǒng)一處理錯誤,那在用Promise.all來處理多個異步任務時候,遇到第一個任務執(zhí)行錯誤的時候就會返回,如何操作才能讓所有任務都執(zhí)行完成,再統(tǒng)一處理錯誤呢
【答】Promise.all 處理多個請求,當所有請求都成功的時候,resolve 一個數(shù)組回來,里面是執(zhí)行結果。如果有一個請求失敗就立刻 reject 那個錯誤來,所以這個地方我們不能使用 Promise.all 來實現(xiàn)。Promise 有一個 allSettled 方法,developer.mozilla.org/en-US/docs/…
Event
發(fā)布訂閱模式,Node.js 內置events 模塊
比如HTTP server on('request')
事件監(jiān)聽
const EventEmitter = require("events");class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter(); myEmitter.on("event", () => { console.log("an event occurred!"); }); myEmitter.emit("event");const http = require("http");const server = http.createServer((req, res) => { res.end("hello!!! this is YK!!!"); }); server.on("request", (req, res) => { console.log(req.url); }); server.listen(3000);復制代碼
看完上述內容,你們掌握Node.js中的異步編程的示例分析的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!