接下來要學習如何在 Node.js 中進行錯誤處理與日誌管理,提升應用程式的穩定性與可維護性。
在 Node.js 中,錯誤大致可以分為兩類:
js
function divide(a, b) {
try {
if (b === 0) {
throw new Error('Cannot divide by zero');
}
return a / b;
} catch (err) {
console.error('Error:', err.message);
}
}
console.log(divide(4, 2)); // Output: 2
console.log(divide(4, 0)); // Output: Error: Cannot divide by zero
實際打入 Node.js ,執行結果會如下:
try-catch 適用於同步程式中的錯誤捕捉。
在非同步程式中,例如回調函數或 Promise,需要不同的方式來處理錯誤。
使用回調函數處理錯誤:
js
const fs = require('fs');
fs.readFile('nonexistent.txt', 'utf8', (err, data) => {
if (err) {
return console.error('Error reading file:', err.message);
}
console.log(data);
});
實際打入 Node.js ,執行結果會如下:
使用 Promise 和 async/await 捕捉錯誤:
js
const fsPromises = require('fs').promises;
async function readFileAsync() {
try {
const data = await fsPromises.readFile('nonexistent.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('Error reading file:', err.message);
}
}
readFileAsync();
實際打入 Node.js ,執行結果會如下:
async/await 配合 try-catch 可以流暢的處理非同步錯誤。
若錯誤未被捕捉,可能導致應用崩潰。Node.js 提供了全域性的錯誤處理機制,幫助應用處理未預期的錯誤。
捕捉未處理的 Promise 錯誤:
js
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
實際打入 Node.js ,執行結果會如下:
捕捉未捕獲的異常:
js
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err.message);
// 可選:關閉應用程式
process.exit(1);
});
實際打入 Node.js ,執行結果會如下:
這些全域處理機制應該僅作為最後的防線,在應用程式中還是要盡量處理好所有可預期的錯誤。
日誌管理是一個良好維護應用程式的關鍵。在 Node.js 中,可以使用專門的日誌套件來提升日誌管理的靈活性與可讀性。
Node.js 內建的 console 是最簡單的日誌工具,可以用於開發和基本錯誤記錄。
js
console.log('This is an info log');
console.error('This is an error log');
然而,console 的功能有限,且難以進行更高級的日誌管理。
winston 是一個功能強大的 Node.js 日誌管理庫,可以記錄不同級別的日誌、將日誌儲存到文件,並支援不同的傳輸(例如文件、控制台、第三方服務)。
安裝 winston:
bash
npm install winston
配置 winston:
js
const winston = require('winston');
// 建立 logger
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
// 若在開發環境,則同時輸出到控制台
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple(),
}));
}
// 使用 logger 記錄日誌
logger.info('This is an info log');
logger.error('This is an error log');
實際運行 ,執行結果會如下:
在這個例子中,winston 可以將日誌輸出到文件(如 error.log 和 combined.log),並且在開發環境中會將日誌輸出到控制台。
在日誌管理中,通常會根據日誌的重要性分為不同的級別:
最後實際將錯誤處理與日誌系統結合,記錄應用程式中的錯誤處理它們。
js
process.on('unhandledRejection', (reason, promise) => {
logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`);
// 可選:關閉應用程式
process.exit(1);
});
process.on('uncaughtException', (err) => {
logger.error(`Uncaught Exception: ${err.message}`);
// 可選:關閉應用程式
process.exit(1);
});
今天探討了如何在 Node.js 中處理錯誤並記錄日誌。通過合理的錯誤處理,可以讓應用在錯誤發生時保持穩定;而透過日誌管理,能夠追蹤應用程式的行為並快速診斷問題。在後續的開發中,這些概念和工具將大大提升應用程式的可維護性。