Generator.throw() - Ném lỗi vào Generator
Generator function (function*) có thể tạm dừng và tiếp tục. generator.throw() cho phép **ném một lỗi vào generator** tại vị trí yield hiện tại, bắt lỗi bằng try/catch bên trong generator, sau đó tiếp tục thực thi.
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Generator throw()</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
.result, .sample { font-size: 18px; font-weight: 500; color: rebeccapurple; font-family: monospace; }
.result { color: red; }
button { padding: 8px 16px; margin-right: 10px; cursor: pointer; }
</style>
</head>
<body>
<h1>generator.throw() method trong JavaScript</h1>
<div class="sample"></div>
<div class="result"></div>
<button class="btn-next">HIỂN THỊ SỐ</button>
<button class="btn-throw">NÉM LỖI</button>
<h3>Nhấn nút để tăng số hoặc ném lỗi vào generator</h3>
<script>
const buttons = document.querySelectorAll(".Btn");
const resEle = document.querySelector(".result");
const sampleEle = document.querySelector(".sample");
// Generator function
function* increment() {
let num = 0;
while (true) {
try {
yield num++;
} catch (err) {
// Bắt lỗi từ generator.throw()
resEle.textContent = "Lỗi bắt được: " + err.message + "\n";
}
}
}
const inc = increment();
// Nút 1: Tiếp tục generator (next)
buttons[0].addEventListener("click", () => {
const result = inc.next();
sampleEle.textContent = result.value + " ";
});
// Nút 2: Ném lỗi vào generator
buttons[1].addEventListener("click", () => {
inc.throw(new Error("Một số lỗi đã xảy ra"));
});
</script>
</body>
</html>
Luồng thực thi
function* gen() {
try {
yield 1; // Tạm dừng tại đây
yield 2; // Tiếp tục sau throw()
yield 3;
} catch (e) {
console.log('Bắt lỗi:', e.message);
yield 'recovered'; // Có thể yield sau khi bắt lỗi
}
}
const g = gen();
g.next(); // { value: 1, done: false } - tạm dừng ở yield 1
g.throw(new Error('Oops'));
// Nhảy vào catch block, in "Bắt lỗi: Oops"
// Tiếp tục chạy, yield 'recovered'
// Trả về { value: 'recovered', done: false }
g.next(); // { value: 3, done: false }
g.next(); // { value: undefined, done: true }
So sánh next() vs throw() vs return()
| Phương thức | Hành động | Giá trị yield expression | Dùng khi |
|---|---|---|---|
next(val) | Tiếp tục bình thường | val | Bình thường |
throw(err) | Ném lỗi tại yield | Ném exception (catch block) | Xử lý lỗi, cancel |
return(val) | Kết thúc generator | Không chạy (finally chạy) | Cleanup, forced exit |
Ứng dụng thực tế: Async flow control
function* fetchUserData(userId) {
try {
const profile = yield fetch(`/api/users/${userId}`).then(r => r.json());
const posts = yield fetch(`/api/users/${userId}/posts`).then(r => r.json());
return { profile, posts };
} catch (error) {
// Bắt lỗi từ bất kỳ yield nào
yield { error: error.message };
}
}
const gen = fetchUserData(123);
// UI gọi next() lần 1 -> fetch profile
// UI gọi next() lần 2 -> fetch posts
// Nếu lỗi mạng -> UI gọi throw(error) -> generator catch và yield error object
Lưu ý
- Ném lỗi khi generator chưa start (chưa next()) → lỗi ném ra ngoài, không bắt được.
- Sau
throw(), generator tiếp tục từ catch block (nếu có) hoặc kết thúc (done: true). finallyblock luôn chạy khi generator kết thúc (bởi return, throw, hoặc hết code).