Trong JavaScript, generators cung cấp một cách mới để làm việc với các hàm và trình lặp.
Sử dụng generator,
- bạn có thể dừng thực thi một hàm từ bất kỳ đâu bên trong hàm
- và tiếp tục thực thi mã từ vị trí đã dừng
Tạo Generators trong JavaScript
Để tạo một generator, bạn cần định nghĩa một hàm generator với biểu tượng function*
. Các đối tượng của các hàm generator được gọi là generators.
// define a generator function
function* generator_function() {
... .. ...
}
// creating a generator
const generator_obj = generator_function();
Chú ý: Hàm generator được biểu thị bằng ký hiệu *
. Bạn có thể sử dụng cả function* generatorFunc() {...}
hoặc function *generatorFunc(){...}
để tạo chúng.
Sử dụng yield để Tạm dừng Thực thi
Như đã đề cập ở trên, bạn có thể tạm dừng thực thi của một hàm generator mà không cần thực thi toàn bộ thân hàm. Để làm điều đó, chúng ta sử dụng từ khóa yield
. Ví dụ,
// generator function
function* generatorFunc() {
console.log("1. code before the first yield");
yield 100;
console.log("2. code before the second yield");
yield 200;
}
// returns generator object
const generator = generatorFunc();
console.log(generator.next());
Kết quả
1. code before the first yield
{value: 100, done: false}
Ở đây,
- Một đối tượng generator có tên
generator
được tạo ra. - Khi gọi
generator.next()
, mã cho đếnyield
đầu tiên được thực thi. Khi gặpyield
, chương trình trả về giá trị và tạm dừng hàm generator.
Chú ý: Bạn cần gán các đối tượng generator cho một biến trước khi bạn sử dụng nó.
Hoạt động của Nhiều Khai báo yield
Biểu thức yield
trả về một giá trị. Tuy nhiên, không giống như câu lệnh return
, nó không chấm dứt chương trình. Đó là lý do tại sao bạn có thể tiếp tục thực thi mã từ vị trí đã được khai báo yield
cuối cùng. Ví dụ,
function* generatorFunc() {
console.log("1. code before first yield");
yield 100;
console.log("2. code before the second yield");
yield 200;
console.log("3. code after the second yield");
}
const generator = generatorFunc();
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
Kết quả
1. code before first yield
{value: 100, done: false}
2. code before second yield
{value: 200, done: false}
{value: undefined, done: true}
Dưới đây là cách chương trình này hoạt động.
- Câu lệnh
generator.next()
đầu tiên thực thi mã cho đến câu lệnh yield đầu tiên và tạm dừng việc thực thi của chương trình. - Câu lệnh
generator.next()
thứ hai khởi đầu chương trình từ vị trí đã tạm dừng. - Khi tất cả các phần tử được truy cập, nó trả về {value: undefined, done: true}.
Hoạt động của hàm generator trong JavaScript
Truyền Tham số vào Các Hàm Generator
Bạn cũng có thể truyền tham số vào một hàm generator. Ví dụ,
// generator function
function* generatorFunc() {
// returns 'hello' at first next()
let x = yield 'hello';
// returns passed argument on the second next()
console.log(x);
console.log('some code');
// returns 5 on second next()
yield 5;
}
const generator = generatorFunc();
console.log(generator.next());
console.log(generator.next(6));
console.log(generator.next());
Kết quả
{value: "hello", done: false}
6
some code
{value: 5, done: false}
{value: undefined, done: true}
Trong chương trình trên,
- Câu lệnh
generator.next()
đầu tiên trả về giá trị của câu lệnhyield
(trong trường hợp này, ‘hello’). Tuy nhiên, giá trị không được gán cho biến x tronglet x = yield 'hello';
{value: “hello”, done: false} - Khi
generator.next(6)
được gọi, mã bắt đầu lại tạilet x = yield 'hello';
và tham số 6 được gán cho x. Ngoài ra, mã còn lại được thực thi cho đến câu lệnhyield
thứ hai.6 một số mã {value: 5, done: false} - Khi câu lệnh
next()
thứ ba được thực thi, chương trình trả về {value: undefined, done: true}. Điều này xảy ra vì không còn câu lệnhyield
nào khác. {value: undefined, done: true}
Generators được Sử dụng để Thực hiện Các đối tượng Trình lặp
Generators cung cấp một cách dễ dàng hơn để thực hiện iterators.
Nếu bạn muốn thực hiện một trình lặp thủ công, bạn phải tạo một trình lặp với phương thức next()
và lưu trạng thái. Ví dụ,
// creating iterable object
const iterableObj = {
// iterator method
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step === 1) {
return { value: '1', done: false};
}
else if (step === 2) {
return { value: '2', done: false};
}
else if (step === 3) {
return { value: '3', done: false};
}
return { value: '', done: true };
}
}
}
}
for (const i of iterableObj) {
console.log(i);
}
Kết quả
1
2
3
Vì generators là các đối tượng trình lặp, bạn có thể thực hiện một trình lặp một cách dễ dàng hơn. Sau đó, bạn có thể lặp qua các generators bằng vòng lặp for...of
. Ví dụ,
// generator function
function* generatorFunc() {
yield 1;
yield 2;
yield 3;
}
const obj = generatorFunc();
// iteration through generator
for (let value of obj) {
console.log(value);
}
Các Phương thức của Generator
Phương thức | Mô tả |
---|---|
next() |
Trả về một giá trị của câu lệnh yield |
return() |
Trả về một giá trị và chấm dứt generator |
throw() |
Ném một lỗi và chấm dứt generator |
Từ khóa return và yield trong JavaScript
Từ khóa return | Từ khóa yield |
---|---|
Trả về giá trị và chấm dứt hàm. | Trả về giá trị và tạm dừng hàm nhưng không chấm dứt hàm. |
Có sẵn trong cả các hàm thông thường và hàm generator. | Chỉ có sẵn trong hàm generator. |
Hàm Generator JavaScript Với return
Bạn có thể sử dụng câu lệnh return
trong một hàm generator. Câu lệnh return
trả về một giá trị và chấm dứt hàm (tương tự như hàm thông thường). Ví dụ,
// generator function
function* generatorFunc() {
yield 100;
return 123;
console.log("2. some code before second yield");
yield 200;
}
// returns generator object
const generator = generatorFunc();
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
Kết quả
{value: 100, done: false}
{value: 123, done: true}
{value: undefined, done: true}
Trong chương trình trên, khi gặp câu lệnh return
, nó trả về giá trị và thuộc tính done
trở thành true
, và hàm chấm dứt. Do đó, phương thức next()
sau câu lệnh return
không trả về bất cứ điều gì.
Chú ý : Bạn cũng có thể sử dụng phương thức return()
thay vì câu lệnh return
, ví dụ generator.return(123);
trong đoạn mã trên.
Phương thức throw của Generator trong JavaScript
Bạn có thể rõ ràng ném một lỗi vào hàm generator bằng cách sử dụng phương thức throw(). Sử dụng phương thức throw()
sẽ ném một lỗi và chấm dứt hàm. Ví dụ,
// generator function
function* generatorFunc() {
yield 100;
yield 200;
}
// returns generator object
const generator = generatorFunc();
console.log(generator.next());
// throws an error
// terminates the generator
console.log(generator.throw(new Error('Error occurred.')));
console.log(generator.next());
Kết quả
{value: 1, done: false}
Error: Error occurred.
Các Ứng dụng của Generators
- Generators giúp chúng ta viết mã sạch hơn khi viết các nhiệm vụ bất đồng bộ.
- Generators cung cấp một cách dễ dàng hơn để thực hiện các trình lặp.
- Generators thực thi mã của nó chỉ khi cần.
- Generators tiết kiệm bộ nhớ.
Generators được giới thiệu trong ES6. Một số trình duyệt có thể không hỗ trợ việc sử dụng generators.
- Bài đăng trên blog này ban đầu được đăng tại: https://www.programiz.com/