非同步程式設計、事件驅動、Promises以及Async/Await是Node.js強大的支柱。非同步程式設計帶來效能的飆升,事件驅動模型使應用程式更靈活反應。在這篇內容中,我們將深入解析這些概念。理解非同步程式設計非同步程式設計基於事件驅動模型,使得應用程式能夠u同時處理多個任務/u,而不需等待一個操作完成後再執行下一個。這樣的設計方式顯著提高了應用程式的反應速度,尤其適用於處理大量並發請求的場景。在Node.js中,當某個非同步操作開始執行時,不會阻塞後續的程式碼執行,而是將回調函式放入事件循環中,等待操作完成後再被調用。避免了傳統同步編程中的等待時間。例如我們可以使用許多API來實現非同步程式設計,如文件讀寫、網路請求等。然而,非同步程式設計也帶來了一些挑戰,最主要的是處理異常和保持程式碼清晰可讀性。為了解決這些問題,Node.js引入了Promise和Async/Await這兩種概念。以Node.js中的文件讀寫操作為範例:constfsrequire"fs";console.log"開始讀取文件";fs.readFile"example.txt","utf8",err,data{iferrthrowerr;//文件讀取完成後會執行以下指令console.log文件內容:${data};};//會直接執行以下指令,而不是等待文件讀取完成console.log"讀取文件操作進行中";在這個範例中readFile函式是非同步的,當文件讀取完成後,回調函式被觸發。而在回調函式之後的console.log會立即執行,而不需等待文件讀取操作完成。Callbacks、Promises、Async/Await在Node.js的非同步程式設計中,Callbacks、Promises和Async/Await是不可忽視的重要概念。這三者代表著不同的非同步處理方式,具有各自的優勢和適用場景。以下將深入探討Callbacks、Promises和Async/Await的特性,並透過範例演示它們在實際開發中的應用。Callbacks回調函式Callbacks是最基本的非同步處理方式,在Node.js中被廣泛使用。它的基本思想是將一個函式作為參數傳遞給另一個函式,在後者完成任務後呼叫前者。以下是一個簡單的Callbacks例子:functiongetDataFromServernext{/用timer模擬透過server取得資料的情境在送出請求的1秒後取得資料/setTimeout{console.log"資料取得完成";//傳遞資料內容next"資料";},1000;};getDataFromServerdata{//取得資料後執行下一個指令console.logdata;};在這個例子中,getDataFromServer函式模擬異步操作,並在完成後呼叫next函式。Callbacks的缺點在於可能產生回調地獄CallbackHell,使得程式碼難以維護。PromisesPromises是一種更為結構化的非同步處理方式,用於解決Callbacks帶來的可讀性問題。Promises有三種狀態pending、fulfilled和rejected,分別表示異步操作未完成、成功完成和失敗。以下是一個Promises的範例:functiongetDataFromServer{returnnewPromiseres,rej{setTimeout{console.log"資料取得完成";res"資料";},1000;};};getDataFromServer.thendata{//取得資料後執行下一個指令console.logdata;}.catcherr{console.errorerr;};在這個例子中,getDataFromServer返回一個Promise,可以使用.then處理成功狀態,使用.catch處理失敗狀態。Promises使得非同步程式碼更具結構性。Async/Await:Async/Await是建構在Promises之上的語法糖,使非同步程式碼更接近同步風格。以下是一個Async/Await的範例://搭配上asyncasyncfunctiongetDataFromServer{returnnewPromiseres,rej{setTimeout{console.log"資料取得完成";res"資料";},1000;};};asyncgetData{//使用await,等待取得資料後才會進行下一步指令constdataawaitgetDataFromServer;console.logdata;};getData;透過async標記函式為異步,以及使用await等待Promise的解析,我們能夠以更簡潔的方式寫出非同步程式碼,提高可讀性。事件驅動架構事件驅動架構基於觀察者模式,其中一個對象維護一個訂閱者列表,並在某些事件發生時通知所有訂閱者。在Node.js中,這種模式得以實現,使得應用程式能夠有效地處理大量的並發請求。EventEmitter的使用Node.js核心模塊提供了EventEmitter類別,它是實現事件驅動的基礎。以下是一個簡單的範例:constEventEmitterrequire"events".EventEmitter;consteventnewEventEmitter;event.on"event",function{console.log"事件";};/透過timer設定1秒後數發事件/setTimeoutfunction{event.emit"event";},1000;在這個例子中,event是一個事件發射器,當使用on方法註冊了一個事件監聽器後,使用emit方法觸發了事件。所有註冊的監聽器都將被呼叫。HTTP伺服器實際應用在實際的Node.js應用中,事件驅動特別適用於處理HTTP請求。以下是一個簡單的HTTP伺服器的例子:consthttprequire"http";//建立一個HTTP伺服器constserverhttp.createServerreq,res{res.send"HelloWorld";};//註冊伺服器啟動事件server.on"listening",{console.log"Serveron";};//啟動伺服器server.listen3000;在這個例子中,createServer方法返回一個具有事件驅動特性的伺服器對象。通過註冊listening事件,我們能夠在伺服器啟動時執行額外的邏輯。這種方式使得我們能夠更靈活地處理伺服器的生命週期事件。事件驅動的優勢事件驅動架構的一大優勢是元件之間的解耦。不同的元件可以通過事件的發射和監聽來進行通信,而不需要直接引用對方。這使得代碼更容易擴展和維護。系列文章ahref"https://pardn.io/blog/nodejsinstall"target"self"Node.js.JavaScript的後端魔法/aPromise與Async/Await的非同步設計ahref"https://pardn.io/blog/nodejshelloworld"target"self"建立第一個Node.js應用程式有多難?/aahref"https://pardn.io/blog/nodejsexpress"target"self"什麼?Express竟然如此的好用/aahref"https://pardn.io/blog/nodejsmongodbmysql"target"self"前進資料庫!MongoDB與MySQL/aahref"https://pardn.io/blog/nodejsmiddleware"target"self"中介軟體Middleware與定制流程/aahref"https://pardn.io/blog/nodejspugejs"target"self"服務端渲染SSR的救星!Pug與EJS/aahref"https://pardn.io/blog/nodejsjwtxsscsp"target"self"實作JWT會員登入以及防範SQL注入與XSS攻擊/aahref"https://pardn.io/blog/nodejsrestfulapi"target"self"RESTfulAPI該怎麼設計?/aahref"https://pardn.io/blog/nodejsmochasupertest"target"self"Mocha?Supertest?單元與整合測試?/aahref"https://pardn.io/blog/nodejspm2"target"self"搭配Pm2讓Node.js持久化在線/a相關連結作者:PardnChiu]https://github.com/pardnchiuNode.js官方網站:https://nodejs.org/zhtw]https://nodejs.org/zhtw