2.1 Cú pháp của generators
Generators trong JavaScript là những hàm đặc biệt cho phép điều khiển việc thực thi mã. Chúng có thể tạm dừng việc thực thi và nối lại sau đó, điều này làm cho chúng trở thành công cụ mạnh mẽ để làm việc với mã bất đồng bộ, iterators và các nhiệm vụ phức tạp khác.
Generators được định nghĩa thông qua hàm function* (chú ý dấu sao). Bên trong generator, ta sử dụng từ khóa yield để tạm dừng thực thi và trả về giá trị.
Khai báo một generator:
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
Tạo đối tượng generator
Gọi generator không thực thi nội dung của nó ngay lập tức. Thay vào đó, nó trả về một đối tượng generator, mà ta có thể sử dụng để lặp qua các giá trị:
const gen = generatorFunction();
2.2 Sử dụng generators
Phương thức next()
Phương thức next() được sử dụng để tiếp tục thực thi generator đến từ khóa yield tiếp theo. Nó trả về một đối tượng với hai thuộc tính:
value: giá trị được trả về bởi từ khóayielddone: giá trị logic, cho biết liệu generator đã hoàn thành (true) hay chưa (false)
Ví dụ sử dụng phương thức next():
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
Thực hiện lặp qua generator
Generators có thể được sử dụng với vòng lặp for...of để lặp qua các giá trị.
Ví dụ lặp qua generator:
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const gen = generatorFunction();
for (const value of gen) {
console.log(value);
}
// In ra: 1
// In ra: 2
// In ra: 3
Ví dụ trả về giá trị
Generators có thể trả về giá trị thông qua từ khóa return:
function* generatorFunction() {
yield 1;
yield 2;
return 3;
yield 4; // Yield này sẽ không bao giờ được thực thi
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }
console.log(gen.next()); // { value: undefined, done: true }
2.3 Sử dụng phức tạp của generators
Tương tác với generator
Phương thức next() có thể nhận một đối số, đối số này sẽ được truyền vào generator và có thể được sử dụng bên trong nó.
Ví dụ truyền giá trị vào generator:
function* generatorFunction() {
const value1 = yield 1;
const value2 = yield value1 + 2;
yield value2 + 3;
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next(10)); // { value: 12, done: false }
console.log(gen.next(20)); // { value: 23, done: false }
console.log(gen.next()); // { value: undefined, done: true }
Xử lý lỗi
Generators cho phép xử lý lỗi thông qua khối try...catch.
Ví dụ xử lý lỗi:
function* generatorFunction() {
try {
yield 1;
yield 2;
} catch (error) {
console.log('Caught lỗi:', error);
}
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.throw(new Error('Có gì đó không ổn rồi'))); // Caught lỗi: Error: Có gì đó không ổn rồi
// { value: undefined, done: true }
Ví dụ generator để tạo dãy vô hạn
Generators có thể được sử dụng để tạo dãy vô hạn của các giá trị:
function* infiniteSequence() {
let i = 0;
while (true) {
yield i++;
}
}
const gen = infiniteSequence();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// và cứ thế
2.4 Ví dụ sử dụng thực tế
Ví dụ 1: Generator để lặp qua một đối tượng
function* objectEntries(obj) {
const keys = Object.keys(obj);
for (const key of keys) {
yield [key, obj[key]];
}
}
const obj = { a: 1, b: 2, c: 3 };
const gen = objectEntries(obj);
for (const [key, value] of gen) {
console.log(`${key}: ${value}`);
}
// In ra:
// a: 1
// b: 2
// c: 3
Ví dụ 2: Generator để triển khai một iterator đơn giản
const myIterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
};
for (const value of myIterable) {
console.log(value);
}
// In ra: 1
// In ra: 2
// In ra: 3
Generators trong JavaScript là công cụ mạnh để điều khiển việc thực thi mã, tạo iterator và làm việc với các thao tác bất đồng bộ. Hiểu cú pháp và cách sử dụng generators giúp tạo ra mã linh hoạt và dễ đọc hơn, đặc biệt khi làm việc với dãy dữ liệu và các tác vụ bất đồng bộ.
GO TO FULL VERSION