Generator trong JavaScript là một loại hàm đặc biệt có khả năng tạm dừng quá trình thực thi và tiếp tục lại sau đó. Điều này làm cho nó trở nên hữu ích trong việc quản lý các tác vụ bất đồng bộ hoặc khi xử lý các chuỗi giá trị lớn mà không cần tải tất cả dữ liệu vào bộ nhớ cùng một lúc.
Hàm generator được định nghĩa bằng cách sử dụng cú pháp có từ khóa function*
(dấu *
đứng sau từ khóa function
).
function* generatorFunction() { // Code trong generator }
Bên trong một generator, từ khóa yield
được sử dụng để tạm dừng quá trình thực thi và trả về một giá trị tạm thời. Khi generator tiếp tục, nó sẽ tiếp tục từ nơi nó đã tạm dừng.
function* simpleGenerator() { console.log('Start'); yield 1; console.log('After first yield'); yield 2; console.log('After second yield'); yield 3; console.log('End'); } const generator = simpleGenerator(); console.log(generator.next()); // Start, { value: 1, done: false } console.log(generator.next()); // After first yield, { value: 2, done: false } console.log(generator.next()); // After second yield, { value: 3, done: false } console.log(generator.next()); // End, { value: undefined, done: true }
yield
: Tạm dừng hàm generator tại mỗi điểm nó xuất hiện và trả về giá trị. Sau đó, quá trình thực thi sẽ tạm dừng tại đó cho đến khi bạn tiếp tục nó bằng cách gọi next()
.generator.next()
: Gọi phương thức next()
sẽ tiếp tục quá trình thực thi generator từ điểm mà nó đã tạm dừng. Mỗi lần gọi next()
, generator sẽ tiếp tục thực thi cho đến khi nó gặp lệnh yield
tiếp theo hoặc kết thúc hàm.next()
: Mỗi lần gọi next()
trả về một đối tượng có cấu trúc { value: <giá trị>, done: <true/false> }
. Thuộc tính value
là giá trị được trả về từ lệnh yield
, còn done
cho biết liệu generator đã hoàn thành hay chưa.next()
được gọi, giá trị mới sẽ được sinh ra. Điều này giúp tiết kiệm bộ nhớ và tăng hiệu suất.async
/await
.Bạn có thể sử dụng generator cùng với vòng lặp for...of
để lặp qua các giá trị mà không cần gọi next()
thủ công.
function* numberGenerator() { yield 1; yield 2; yield 3; } for (let value of numberGenerator()) { console.log(value); // In ra: 1, 2, 3 }
Mặc dù bản thân generator không phải là bất đồng bộ, nhưng nó có thể được sử dụng kết hợp với các tác vụ bất đồng bộ để quản lý luồng dễ dàng hơn.
function* asyncGenerator() { yield new Promise(resolve => setTimeout(() => resolve('Task 1 completed'), 1000)); yield new Promise(resolve => setTimeout(() => resolve('Task 2 completed'), 1000)); } const gen = asyncGenerator(); gen.next().value.then(console.log); // Sau 1 giây: 'Task 1 completed' gen.next().value.then(console.log); // Sau 1 giây tiếp: 'Task 2 completed'
async
/await
, nhưng generator cũng có thể được sử dụng để quản lý các tác vụ bất đồng bộ theo cách thức tuần tự mà không cần callback hoặc promise phức tạp.Generators là một công cụ mạnh mẽ trong JavaScript để xử lý luồng dữ liệu tuần tự, có thể tạm dừng và tiếp tục. Chúng được sử dụng trong các tình huống xử lý dữ liệu lớn, làm việc với bất đồng bộ, hoặc bất cứ nơi nào cần tiết kiệm tài nguyên bằng cách tính toán giá trị theo yêu cầu.