Node.js 程式札記 : 異步處理 - 回調函式、Promise、以及 Async/Await

閱讀時間約 1 分鐘

在學習 Node.js 時,異步處理是其中一個非常重要的概念,因為Node.js是一個非阻塞I/O的運行環境,所以理解如何處理異步操作對於開發者來說至關重要。本篇文章將介紹 Node.js 中常見的三種異步處理方式:回調函式、Promise、以及 Async/Await。

回調函式 (Callback Functions)

在 Node.js 中,許多內建模組都是基於回調函式設計的,當一個函式需要執行一個耗時的操作時,它會接受一個回調函式,這個回調函式會在操作完成後被調用。

什麼是回調?

在 JavaScript 中,「回調」是一種將函式作為參數傳遞給另一個函式的方式,當某個操作完成時,這個函式(即回調函式)會被調用,從而「回調」到指定的操作上。

為什麼要使用回調?

考慮一個情境:你需要讀取一個文件,這是一個耗時的操作。如果你的程序在讀取文件時停止,等待文件讀取完成後再繼續執行其他程式碼,那麼整個應用程式就會因為這個等待時間而無法處理其他任務。

為了避免這種情況,JavaScript 使用了回調函式的概念,當你請求讀取文件時,你可以傳入一個回調函式,告訴程序在文件讀取完成後要做什麼。這樣,在等待文件讀取的同時,仍然可以繼續執行其他程式碼。

function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: 'Product' };
callback(data);
}, 2000);
}

function handleData(data) {
console.log('Received data:', data);
}

fetchData(handleData);

在這個例子中,fetchData函式模擬了一個異步操作,它在兩秒後取得數據並調用回調函式handleData來處理這些數據。這個回調函式作為參數傳入fetchData,當數據準備好時,fetchData函式「回調」handleData函式,並將數據傳給它。

回調地獄 (Callback Hell)

當你需要執行多個異步操作,而且這些操作需要依次進行時,回調函式就會嵌套在一起。例如,想像你需要依次讀取多個文件,並在每個文件讀取完成後進行某些操作,這時候你的程式碼可能會變成這樣:

const fs = require('fs');

fs.readFile('file1.txt', 'utf8', (err, data1) => {
if (err) throw err;
fs.readFile('file2.txt', 'utf8', (err, data2) => {
if (err) throw err;
fs.readFile('file3.txt', 'utf8', (err, data3) => {
if (err) throw err;
console.log(data1, data2, data3); // 這裡會顯示 data1, data2 和 data3 的內容
});
});
});

這樣的嵌套結構被稱為「回調地獄」,因為它會導致程式碼變得難以閱讀和維護,每一層嵌套都程式碼更加混亂,也更容易出錯。

Promise

為了解決回調地獄的問題,於是就出現了 Promise。Promise 提供了一種更為簡潔的方式來處理異步操作,它使得異步程式碼更加直觀和可讀。

const fs = require('fs').promises;

// 使用Promise讀取多個文件
fs.readFile('file1.txt', 'utf8')
.then(data1 => {
console.log('File 1 content:', data1);
return fs.readFile('file2.txt', 'utf8');
})
.then(data2 => {
console.log('File 2 content:', data2);
return fs.readFile('file3.txt', 'utf8');
})
.then(data3 => {
console.log('File 3 content:', data3);
})
.catch(err => {
console.error('Error reading file:', err);
});

在這個範例中,fs.readFile返回一個Promise對象。我們可以使用then來處理成功的結果,使用catch來捕獲錯誤。這種鏈式結構使得程式碼更為整潔,也更容易理解。Promise還提供了Promise.allPromise.race等功能來處理多個異步操作。

Async/Await

Async/Await 是基於 Promise 的一種語法糖,它使得異步程式碼看起來像是同步的,從而提高程式碼的可讀性,是現在處理異步操作的標準方式。

const fs = require('fs').promises;

async function readFile() {
try {
const data = await fs.readFile('example.txt', 'utf8');
console.log('File content:', data);
} catch (err) {
console.error('Error reading file:', err);
}
}

readFile();

在這個範例中,readFile函式被定義為async,這意味著我們可以在其中使用await來等待一個 Promise 完成。這種寫法使得異步操作更加直觀,並且與傳統的同步程式碼風格一致。

總結

異步處理是 Node.js 中不可或缺的一部分,理解和掌握回調函式、Promise、以及Async/Await 三種常見的異步處理方式,可以幫助開發者更好地構建高效且可擴展的應用。回調函式提供了基本的異步處理方式,但容易導致回調地獄;Promise 則解決了這一問題,使程式碼更加整潔;而Async/Await則進一步簡化了異步處理,讓程式碼更加直觀。無論是熟練掌握這些技術,以便在開發Node.js應用時能夠靈活應用。

60會員
91內容數
「梧笙」即「吾生」,意即我的生命,朋友都叫我「阿梧(Awu)」,高雄人。我喜歡學習新技能,從程式設計到網路工具,再到社群經營和影片剪輯。日常興趣是打遊戲、看動漫、讀小說和聽音樂。我會把這些興趣寫成文章,如果你有任何想法或問題,歡迎來信到我的郵箱 aowulife109@gmail.com
留言0
查看全部
發表第一個留言支持創作者!
梧笙の領域展開 的其他內容
由於 Node.js 其非同步和事件驅動的特性,Node.js 特別適合構建高效能的網絡應用程式。本文將介紹 Node.js 的三個基礎概念:事件驅動和非阻塞I/O、模組系統以及 npm 套件管理器。
對於剛開始學習程式設計或想要進一步了解後端開發的人來說,Node.js 是一個非常好的起點。本文將介紹 Node.js 的基本概念、優點以及應用場景,並提供如何在你的電腦上設置開發環境和實作一個簡單的 "Hello World" 範例。
組件之間的通信是 Vue 應用開發中的一個重要方面。Vue 提供了一種名為事件發射(emit)的機制,讓子組件能夠向父組件發送消息。本文將介紹 Vue 中的事件發射(emit)機制,並通過實際範例演示其用法。
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
v-bind 指令是最常用的指令之一,它用於將資料綁定到 HTML 屬性。本文將介v-bindnd指令的使用方法,並透過實際範例幫助你理解v-bindbind 指令。
v-model 指令是 Vue 中一個非常重要的功能,它實現了表單輸入和應用狀態之間的雙向綁定。本文將介紹如何使用 v-model 指令。
由於 Node.js 其非同步和事件驅動的特性,Node.js 特別適合構建高效能的網絡應用程式。本文將介紹 Node.js 的三個基礎概念:事件驅動和非阻塞I/O、模組系統以及 npm 套件管理器。
對於剛開始學習程式設計或想要進一步了解後端開發的人來說,Node.js 是一個非常好的起點。本文將介紹 Node.js 的基本概念、優點以及應用場景,並提供如何在你的電腦上設置開發環境和實作一個簡單的 "Hello World" 範例。
組件之間的通信是 Vue 應用開發中的一個重要方面。Vue 提供了一種名為事件發射(emit)的機制,讓子組件能夠向父組件發送消息。本文將介紹 Vue 中的事件發射(emit)機制,並通過實際範例演示其用法。
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
v-bind 指令是最常用的指令之一,它用於將資料綁定到 HTML 屬性。本文將介v-bindnd指令的使用方法,並透過實際範例幫助你理解v-bindbind 指令。
v-model 指令是 Vue 中一個非常重要的功能,它實現了表單輸入和應用狀態之間的雙向綁定。本文將介紹如何使用 v-model 指令。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
在這篇教學文章中,我們將展示如何使用 Node.js 建立一個簡單的伺服器,並解決常見的跨來源資源共享(CORS)問題,確保伺服器能夠接收並處理來自不同來源的資料。
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
※ 原本狀態:伺服器渲染 這是 MVC 架構下的 request / response 示意圖,在這張圖呈現的架構裡,畫面和資料都由同一個架構處理。 伺服器渲染流程: 瀏覽器針對特定網址送出請求。 路由器解析請求後,轉接給對應的 controller。 controller 按照要求,透過
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
※ 補充說明: ※ npm 常用指令: ◦ npm init–y:快速初始化一個新的 Node.js 並建立一個 package.json 文件的命令。 ◦ npm info 套件名稱 version:快速查詢指定 npm 套件的最新版本號。 ◦ npm install套件名稱:用來安裝
Thumbnail
Node.js是一個JavaScript運行環境。它使用了一個非阻塞、事件驅動的I/O模型,使其非常適合用於數據密集型的即時應用程序。簡單來說,Node.js允許你使用JavaScript來編寫伺服器端代碼。 nvm 安裝nvm Windows : 點擊 Releases · coreybut
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
在這篇教學文章中,我們將展示如何使用 Node.js 建立一個簡單的伺服器,並解決常見的跨來源資源共享(CORS)問題,確保伺服器能夠接收並處理來自不同來源的資料。
主要來講宣告函式跟箭頭函式 : 宣告函式(Function Declaration) 語法: function functionName(parameters) { return result; } 特點: 使用 function 關鍵字 函式名稱是必需的 存在函式
Thumbnail
※ 原本狀態:伺服器渲染 這是 MVC 架構下的 request / response 示意圖,在這張圖呈現的架構裡,畫面和資料都由同一個架構處理。 伺服器渲染流程: 瀏覽器針對特定網址送出請求。 路由器解析請求後,轉接給對應的 controller。 controller 按照要求,透過
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
※ 補充說明: ※ npm 常用指令: ◦ npm init–y:快速初始化一個新的 Node.js 並建立一個 package.json 文件的命令。 ◦ npm info 套件名稱 version:快速查詢指定 npm 套件的最新版本號。 ◦ npm install套件名稱:用來安裝
Thumbnail
Node.js是一個JavaScript運行環境。它使用了一個非阻塞、事件驅動的I/O模型,使其非常適合用於數據密集型的即時應用程序。簡單來說,Node.js允許你使用JavaScript來編寫伺服器端代碼。 nvm 安裝nvm Windows : 點擊 Releases · coreybut
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協