Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Phương thức generator.throw() trong JavaScript

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ườngvalBình thường
throw(err)Ném lỗi tại yieldNém exception (catch block)Xử lý lỗi, cancel
return(val)Kết thúc generatorKhô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).
  • finally block luôn chạy khi generator kết thúc (bởi return, throw, hoặc hết code).