Xử lý lỗi
Exception chưa bắt (uncaughtException)
process.on('uncaughtException') của Node.js so với panic/recover (Go), catch_unwind (Rust), do/catch (Swift) và uncaught exception handler (Java).
- Phiên bản tối thiểu
- Node.js ≥ 12.20Go ≥ 1.0Rust ≥ 1.58Swift ≥ 5.1Java ≥ 25
- Đã chạy thử trên
- Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1
Code Node.js là ES module: lưu file .mjs hoặc đặt "type": "module" trong package.json.
Bài xử lý lỗi và try/catch đã nói về throw/try/catch cho luồng xử lý lỗi thông thường. Ở đây là trường hợp khác: một lỗi thoát khỏi mọi xử lý thông thường và bay thẳng tới top-level — cơ chế bắt cuối cùng trước khi tiến trình sập. Rust có catch_unwind (bọc quanh một lời gọi, giống defer/recover của Go). Swift không có hook toàn cục nào — bọc điểm vào chương trình trong do/catch là cách gần nhất, và một lỗi thật sự không được bắt sẽ khiến runtime crash ngay, không gì cứu được. Java có Thread.setDefaultUncaughtExceptionHandler() — một hook toàn cục đúng như tên gọi, giống hệt process.on('uncaughtException').
Bắt exception ở top-level (uncaughtException vs recover)
process.on("uncaughtException", (err) => {
console.log(`caught exception: ${err.message}`); // → caught exception: my exception
process.exit(1); // log, dọn dẹp rồi exit: cố chạy tiếp sau lỗi này là không an toàn
});
function foo() {
throw new Error("my exception");
}
function main() {
foo();
}
main();
// exit code: 1package main
import (
"fmt"
)
func foo() {
panic("my exception")
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("caught exception: %s", r) // → caught exception: my exception
}
}()
foo()
}
// exit code: 0use std::panic;
fn foo() {
panic!("my exception");
}
fn main() {
panic::set_hook(Box::new(|_| {})); // im lặng dòng "thread panicked at..." mặc định
let result = panic::catch_unwind(foo);
if let Err(payload) = result {
let message = payload.downcast_ref::<&str>().copied().unwrap_or("unknown panic");
println!("caught exception: {message}"); // → caught exception: my exception
}
}
// exit code: 0struct AppError: Error, CustomStringConvertible {
var description: String { "my exception" }
}
func foo() throws {
throw AppError()
}
// Swift không có hook toàn cục: bọc điểm vào chương trình trong do/catch là
// cách gần nhất — một Error không được bắt tới tận top level sẽ crash ngay
// lập tức, không thể can thiệp.
do {
try foo()
} catch {
print("caught exception: \(error)") // → caught exception: my exception
}
// exit code: 0void main() {
Thread.setDefaultUncaughtExceptionHandler((thread, e) -> {
IO.println("caught exception: " + e.getMessage()); // → caught exception: my exception
});
foo();
}
static void foo() {
throw new RuntimeException("my exception");
}
// exit code: 1Mã thoát chia thành hai nhóm: JS và Java đều gọi process.exit(1)/để main thread crash nên thoát với mã khác 0 — cả hai coi "bắt được ở top-level" là dấu hiệu phải dừng lại, không cố chạy tiếp. Go, Rust và Swift đều "nuốt" lỗi bằng recover()/catch_unwind/do-catch rồi để chương trình return bình thường, nên thoát với mã 0.
Tham khảo: github.com/miguelmota/golang-for-nodejs-developers#exceptions