Các hàm generator trong JavaScript
Trong bài viết này, chúng tôi sẽ giải thích về các hàm generator trong JavaScript.
YouTube Video
Các hàm generator trong JavaScript
Các hàm generator trong JavaScript là các hàm đặc biệt khác với các hàm thông thường vì chúng có thể thực hiện thực thi lười biếng và tạm dừng và tiếp tục. Bằng cách hiểu các hàm generator, bạn có thể xử lý hiệu quả các hoạt động bất đồng bộ và xử lý tuần tự dữ liệu lớn. Ở đây, chúng tôi sẽ cung cấp giải thích chi tiết về cách các hàm generator hoạt động, cách sử dụng chúng và các trường hợp sử dụng thực tế.
Hàm Generator là gì?
Một hàm generator được định nghĩa bằng function*
(một định nghĩa hàm có dấu sao) và, không giống như các hàm thông thường, nó có thể tạm dừng việc thực thi giữa chừng và tiếp tục trong khi vẫn giữ trạng thái của nó. Các hàm generator cho phép "thực thi lười biếng" và trả lại kết quả theo từng phần, cho phép quản lý bộ nhớ hiệu quả và xử lý tuần tự.
Cú pháp
1function* generatorFunction() {
2 yield 'First value';
3 yield 'Second value';
4 return 'Done';
5}
Theo cách này, một hàm generator có thể có nhiều biểu thức yield
và sử dụng yield
để tạm dừng việc thực thi của nó. Khi một hàm generator được gọi, phần thân của hàm sẽ không được thực thi ngay lập tức và một đối tượng generator sẽ được trả về. Bạn có thể gọi phương thức next()
trên đối tượng này để tiếp tục hàm từ điểm nó đã tạm dừng.
Cách sử dụng cơ bản của các hàm Generator
Tiếp theo, hãy cùng xem một ví dụ cơ bản về cách sử dụng các hàm generator.
1function* simpleGenerator() {
2 yield 1;
3 yield 2;
4 yield 3;
5}
6
7const gen = simpleGenerator();
8
9console.log(gen.next()); // { value: 1, done: false }
10console.log(gen.next()); // { value: 2, done: false }
11console.log(gen.next()); // { value: 3, done: false }
12console.log(gen.next()); // { value: undefined, done: true }
Một điểm chính cần lưu ý ở đây là generator trả về giá trị mỗi lần với yield
, và miễn là thuộc tính done
là false
, điều đó cho biết vẫn còn các giá trị tiếp theo. Lần gọi cuối cùng đến next()
trả về done: true
, cho biết rằng generator đã hoàn tất.
Từ khóa yield
và việc tạm dừng giá trị
yield
là một từ khóa biểu thị một điểm tạm dừng trong một hàm generator. Giá trị nằm bên phải của yield
sẽ được trả về khi next()
được gọi. Ngoài ra, yield
cho phép giao tiếp hai chiều. Nói cách khác, khi truyền một giá trị làm tham số cho phương thức next()
, giá trị đó sẽ được gửi đến hàm generator.
1function* generatorWithYield() {
2 const value1 = yield 'First yield';
3 console.log('Received value:', value1);
4 const value2 = yield 'Second yield';
5 console.log('Received value:', value2);
6}
7
8const gen = generatorWithYield();
9
10console.log(gen.next()); // { value: 'First yield', done: false }
11console.log(gen.next('Apple')); // Received value: Apple
12 // { value: 'Second yield', done: false }
13console.log(gen.next('Banana'));// Received value: Banana
14 // { value: undefined, done: true }
Trong ví dụ này, lệnh gọi next('Apple')
gửi giá trị 'Apple'
đến hàm generator, nơi giá trị này được sử dụng trong hàm.
Quản lý trạng thái của hàm Generator
Các generator có thể duy trì trạng thái thực thi của chúng, cho phép biểu diễn ngắn gọn các vòng lặp dài hoặc xử lý tuần tự. Ví dụ sau đây minh họa một generator tạo ra các số vô hạn.
1function* infiniteGenerator() {
2 let i = 0;
3 while (true) {
4 yield i++;
5 if (i > 10) {
6 break;
7 }
8 }
9}
10
11const gen = infiniteGenerator();
12
13console.log(gen.next().value); // 0
14console.log(gen.next().value); // 1
15console.log(gen.next().value); // 2
16// Continues...
Generator này liên tục tạo ra các số bằng cách sử dụng vòng lặp while(true)
, cho phép bạn lấy các giá trị khi cần. Điều này cho phép xử lý hiệu quả các tập dữ liệu lớn.
Ứng dụng của Hàm Generator
Hàm generator phù hợp để thực hiện nhiều quy trình một cách tuần tự. Ví dụ, chúng rất hữu ích trong việc xử lý các yêu cầu API tuần tự hoặc chia nhỏ và xử lý các tệp lớn.
1function* apiRequestGenerator() {
2 yield fetch('https://codesparklab.com/json/example1.json');
3 yield fetch('https://codesparklab.com/json/example2.json');
4 yield fetch('https://codesparklab.com/json/example3.json');
5}
Do đó, các generator, có thể được sử dụng để xử lý bất đồng bộ, mang lại lợi ích lớn cho việc xử lý dữ liệu tuần tự hiệu quả.
Generator Bất Đồng Bộ
Generator bất đồng bộ được giới thiệu trong ES2018 cho phép bạn trả lại các giá trị bất đồng bộ tuần tự bằng cách kết hợp async
và yield
. Điều này cho phép bạn viết ngắn gọn việc xử lý bất đồng bộ kết hợp với await
.
Cú pháp
1async function* asyncGenerator() {
2 yield await Promise.resolve(1);
3 yield await Promise.resolve(2);
4 yield await Promise.resolve(3);
5}
6
7const gen = asyncGenerator();
8
9(async () => {
10 for await (const value of gen) {
11 console.log(value); // 1, 2, 3
12 }
13})();
Generator bất đồng bộ có thể truy xuất các giá trị tuần tự bằng cách sử dụng vòng lặp for await...of
. Mẫu này đặc biệt hữu ích khi xử lý các luồng dữ liệu bất đồng bộ.
Ví dụ Thực Tiễn: Đơn Giản Hóa Xử Lý Bất Đồng Bộ với Generator
Hàm generator cũng được sử dụng để đơn giản hóa luồng xử lý bất đồng bộ. Ví dụ, bằng cách kết hợp yield
và Promise
như minh họa dưới đây, bạn có thể viết các thao tác bất đồng bộ trông như đồng bộ.
1function* asyncFlow() {
2 const data1 = yield fetch('https://codesparklab.com/json/example1.json');
3 console.log(data1);
4 const data2 = yield fetch('https://codesparklab.com/json/example2.json');
5 console.log(data2);
6}
7
8const gen = asyncFlow();
9
10function handleAsync(generator) {
11 const next = (promise) => {
12 promise.then((result) => {
13 const { value, done } = generator.next(result);
14 if (!done) {
15 next(value);
16 }
17 });
18 };
19
20 next(generator.next().value);
21}
22
23handleAsync(gen);
Đoạn mã này tuần tự thực hiện các yêu cầu API bằng generator và xử lý kết quả.
Tóm tắt
Hàm generator là một trong những tính năng mạnh mẽ của JavaScript, có khả năng tạm dừng và tiếp tục thực thi một hàm. Điều này cho phép xử lý tuần tự, xử lý bất đồng bộ và thao tác hiệu quả các tập dữ liệu lớn. Hiểu về generator là một bước quan trọng để làm chủ các kỹ thuật nâng cao trong JavaScript.
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.