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

Generator Functions (Hàm tạo sinh) trong JavaScript


Generator Functions cho phép tạm dừng thực thi function và tiếp tục sau. Quản lý flow control, dễ dàng cancel async operations vì có thể pause bất kỳ lúc nào.

Cú pháp

Thêm dấu * sau function:

function *myGenerator() {} 
// hoặc
function* myGenerator() {}
// hoặc
function*myGenerator() {}

Ví dụ cơ bản

<html>
  <body>
    <script>
      function* display() {
        var num = 1;
        while (num < 5) {
          yield num++; // Tạm dừng, trả về giá trị
        }
      }
      
      var myGenerator = display(); // Trả về Generator object (iterator)
      document.write(myGenerator.next().value); // 1
      document.write("<br>" + myGenerator.next().value); // 2
      document.write("<br>" + myGenerator.next().value); // 3
      document.write("<br>" + myGenerator.next().value); // 4
      document.write("<br>" + myGenerator.next().value); // undefined (done: true)
    </script>
  </body>
</html>

Generator Object Methods

MethodMô tả
next(value)Tiếp tục thực thi, truyền value vào yield expression. Trả về {value, done}.
return(value)Kết thúc generator sớm, trả về {value, done: true}.
throw(error)Ném error vào generator tại yield position.

Yield Expression

  • yield value: Tạm dừng, trả value.
  • yield* otherGenerator: Delegate to another generator (yield delegation).
  • const input = yield value: Nhận giá trị từ next(input).

Ví dụ thực tế: Infinite Sequence / Lazy Evaluation

// Infinite counter
function* counter() {
  let i = 0;
  while (true) yield i++;
}

const gen = counter();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
// ... không bao giờ hết

// Fibonacci generator
function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

// Async generator (ES2018) - cho async iteration
async function* fetchPages(url) {
  let nextUrl = url;
  while (nextUrl) {
    const response = await fetch(nextUrl);
    const data = await response.json();
    yield data.items;
    nextUrl = data.nextPage;
  }
}

// Usage: for await (const items of fetchPages('/api/items')) { ... }

Use Cases

  • Lazy evaluation (xử lý dataset lớn, stream).
  • State machine, finite automata.
  • Async flow control (co-routine pattern).
  • Infinite sequences.
  • Custom iterators cho object.

Iterable Protocol

Generator tự động implement Symbol.iterator → dùng được for...of, spread ..., Array.from().

function* range(start, end) {
  for (let i = start; i < end; i++) yield i;
}

console.log([...range(1, 5)]); // [1, 2, 3, 4]
for (const n of range(1, 5)) console.log(n);