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

Generator Function trong JavaScript

Generator function (ES6) là function đặc biệt có thể tạm dừng (pause) và tiếp tục (resume) thực thi, trả về nhiều giá trị theo thời gian qua từ khóa yield.

Cú pháp

function* generatorName() {
  yield value1;
  yield value2;
  return finalValue; // Optional, done: true
}
  • function* — dấu sao đánh dấu generator.
  • yield — tạm dừng, trả về giá trị, chờ next() call tiếp theo.
  • Gọi generator → trả về Generator Object (iterator + iterable).

Ví dụ cơ bản: Đếm ngược

<script>
  function* countDown(start) {
    while (start > 0) {
      yield start--;
    }
  }

  const gen = countDown(3); // Không chạy code ngay!
  
  document.write(gen.next().value + '<br>'); // {value: 3, done: false} → 3
  document.write(gen.next().value + '<br>'); // 2
  document.write(gen.next().value + '<br>'); // 1
  document.write(gen.next().value + '<br>'); // undefined (done: true)
</script>

Generator Object Methods

MethodMô tả
next(value?)Tiếp tục chạy đến yield tiếp theo. Trả về {value, done}. Tham số truyền vào thành giá trị của yield expression.
return(value)Kết thúc generator sớm, trả về {value, done: true}.
throw(error)Ném exception vào generator tại yield hiện tại.

Duyệt Generator với for...of

function* fibonacci(limit) {
  let a = 0, b = 1;
  while (a < limit) {
    yield a;
    [a, b] = [b, a + b];
  }
}

for (const num of fibonacci(100)) {
  document.write(num + ' '); // 0 1 1 2 3 5 8 13 21 34 55 89
}

Yield Delegation: yield*

function* inner() { yield 1; yield 2; }
function* outer() { yield 0; yield* inner(); yield 3; }

[...outer()]; // [0, 1, 2, 3]

Use Case Thực Tế

  • Lazy evaluation: Xử lý dataset lớn/tập vô hạn (stream processing).
  • Async flow control: Kết hợp với Promise (co library) hoặc async/await pattern.
  • State machine: Models finite state rõ ràng.
  • ID generation: Unique ID sequence không cần global variable.

Ví dụ: Infinite ID Generator

function* idGenerator(prefix = 'ID') {
  let count = 0;
  while (true) {
    yield `${prefix}-${++count}`;
  }
}

const ids = idGenerator('USER');
ids.next().value; // "USER-1"
ids.next().value; // "USER-2"
// Không bao giờ hết

Lưu ý

  • Generator là single-pass — duyệt xong không reset được (cần tạo mới).
  • Không dùng arrow function: const gen = *() => {} — syntax error.
  • Trong async context: dùng Async Generator (async function*, for await...of).