Generator function trong javascript

Chúng tôi rất vui mừng được chia sẻ kiến thức sâu sắc về từ khóa Generator la gi để tối ưu hóa nội dung trang web và tiếp thị trực tuyến. Bài viết cung cấp phương pháp tìm kiếm, phân tích từ khóa và chiến lược hiệu quả. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi để cập nhật kiến thức mới.

Xin chào tất cả mọi người hôm nay mình sẽ giới thiệu Generator function trong javascript và nó được sử dụng rất nhiều trong redux-saga một thư viện phối hợp mạnh mẽ với reactjs, mong mọi người theo dõi

Bạn Đang Xem: Generator function trong javascript

1) Generator function là gì

  • Generator là một tính năng mới của tiếng nói JavaScript giới thiệu từ phiên bản ES6. Generator đóng vai trò cơ bản để xây dựng các phương thức xử lý dị đồng bộ khác (side effect), ví dụ: async/await, sagas.
  • Generator function là một function, có khả năng tạm ngưng thực thi trước lúc hàm kết thúc, và có thể tiếp tục chạy ở một thời điểm khác.
  • Generator function có ký tự “*” được đặt sau từ khoá function để phân biệt giữa function thông thường và generator function

Cú pháp

function* functionName([param[, param[, … param]]]) { statements }

Trong số đó

  • functionName: là tên gọi của hàm
  • param: là thông số nguồn vào
  • statements: là phần code mà ta muốn xử lý

Khi tất cả chúng ta gọi Generator function : ” functionName() ” , nó không trả về các kiểu tài liệu cơ bản mà đẩy về một iterator object . Hàm next() của iterator object được sử dụng để truy xuất dến các node tài liệu, sau từng bước resume lại generator function. Khi đó generator function sẽ thực thi hàm cho tới lúc gặp từ khóa yield , hoặc return kế tiếp không được duyệt ở bước trước

Nói cách khác hàm sẽ không còn được thực thi ngay sau khoản thời gian gọi, mà thay vào đó generator function trả về iterator, giống như con trỏ trong vòng lặp. Sau lúc hàm next() của iterator được gọi, generator function sẽ thực thi hàm cho tới lúc gặp từ khóa yield trước hết. yield sẽ trả về giá trị cho iterator, generator function kết thúc cho tới lúc hết giá trị để yield.

Sơ lược về iterator: Iterator là một bộ duyệt dùng để làm duyệt qua một mảng, một list hoặc một collection mà qua mỗi lần duyệt sẽ ghi lại vị trí đã duyệt để từ đó có thể biết và lấy vị trí tiếp theo. Trong Javascript thì iterators có cung cấp phương thức next() và phương thức này sẽ return về thành phần kế tiếp, song song ghi nhận luôn thành phần đã lặp là thành phần next(). Phương thức next() sẽ return về một Object gồm hai tính chất là value và done. done có mức giá trị true nếu Iteration đã hoàn thành, trái lại nó có mức giá trị false.

Lý thuyết hơi dài chút sau đây thì mình sẽ đi vào ví dụ để hiểu hơn nhé

Ví dụ 1

function* generateId() { yield 1; console.log(‘continue to run …’); yield 2; console.log(‘resume’); return 3; } const newId = generateId(); console.log(newId.next()); // {value:1, done:false} console.log(newId.next()); // {value:2, done:false} console.log(newId.next()); // {value:3, done:true}

Kết quả:

Ở ví dụ trên mỗi lần mình gọi newId.next() thì sẽ trả về một object có đạng là {value: any, done: boolean} trong đó:

  • value: kết quả của việc thực thi biểu thức [expression] sau lệnh yield
  • done: nhận giá trị false nếu quá trình generator chưa hoàn thành, trái lại sẽ trả về true.

Xem Thêm : Thức ăn của tôm là gì để đảm bảo chất lượng mùa vụ ?

Một số phương thức của generator:

  • next(): Tiếp tục thực thi hàm cho tới lúc gặp yield or return sẽ trả về một object có dạng {value: any, done: true/false}
  • return(): Dừng generator function và return kết quả có dạng {value: any, done: true}
  • throw(): quăng 1 lỗi vào trong generator function (song song kết thúc generator, trừ khi được bắt lại trong generator đó). return object {value: any, done: true/false}

Ví dụ 2 sử dụng return ()

function* generateId() { yield 1; yield 2; yield 3; } const newId = generateId(); console.log(newId.next()); console.log(newId.next()); console.log(newId.return(‘ahihi’));

Kết quả:

Ở ví dụ trên thì mình có gọi gấp đôi next() sau đó gọi đến return() thì hàm sẽ bị tạm ngưng không thực thi phía dưới nữa. ở trong return() mình có truyền vào giá trị là ahihi vậy nên kết quả nhận được sẽ là {value: ‘ahihi’, done:true} giả sử nếu mình không truyền giá trị nào vào thì kết quả sẽ nhận được là {value: ‘undefined’, done:true}

Ví dụ 3 sử dụng throw()

function* gen() { while (true) { try { yield 42 } catch (e) { console.log(e.message) return; } } } const g = gen() console.log(g.next()) // { value: 42, done: false } console.log(g.throw(new Error(‘Something went wrong’)))

Kết quả:

Ở ví dụ trên khi gọi tới throw() thì một lỗi sẽ tiến hành trả ra và generator function sẽ tạm ngưng và không thực thi nữa

Hai ví dụ trên mình đều phải có truyền thông số vào cho return() và throw() còn next() thì mình chưa truyền vậy truyền thông số vào cho next() thì sẽ thế nào nhỉ? vậy mình cùng xem ví dụ sau nhé

Ví dụ truyền thông số cho next()

Hàm next có param truyền vào nó (next(param)) thì param đấy là giá trị thay thế của yield hiện nay đang bị tạm ngưng trước đó trong hàm generator

Do đó, hàm next trước hết dù có truyền param vào cũng trở nên bỏ qua bởi vì khi đối chiếu với hàm next trước hết, vẫn chưa tồn tại yield nào hiện nay đang bị tạm ngưng. Tức thị khi đối chiếu với lời gọi next trước hết thì next() = next(undefined) = next(null) = next(true) = next(100) = next(“any string”) = next([]) = next({key: “value”})

Xem Thêm : Dịch vụ hậu mãi là gì? Đặc điểm và tầm quan trọng của dịch vụ hậu mãi

function* testGen() { const i = 5 * (yield 100); console.log(“Gia tri cua i = “, i); const j = yield (2 * i) / 4; console.log(“Gia tri cua j”, j); const k = i + (yield j); console.log(“Gia tri cua k”, k); } const gen = testGen(); console.log(gen.next()); console.log(gen.next(20)); console.log(gen.next(10)); console.log(gen.next());

Kết quả:

Ở ví dụ trên

  • Lần gọi next() trước hết thì kết quả nhận được là value: 100 và tạm ngưng ở trước yield 100

  • Lần gọi tiếp theo next(20) thì lần này giá trị truyền vào là 20 sẽ thay thế cho yield 100 tức là const i = 5 * (yield 100) sẽ trở thành const i = 5 * 20 và i lúc này sẽ có mức giá trị là i = 5 * 20 = 100. Giá trị trả về của next(20) là (2*100)/4 = 50 và tạm ngưng trướcyield (2*i)/4

  • Lời gọi tiếp theo next(10) thì giá thị 10 sẽ thay thế cho const j = yield (2*i)/4 lúc này giá trị trả về cho next(10) là 10 và dự lại trướcyield j

  • Lần gọi tiếp theo next() mình không có truyền thông số nào vào nên giái trị lúc này ở yield j sẽ là undefined và khi i = 100 và cộng với undefined thì kết quả của k là NaN vậy mọi người lưu ý (khi sử dụng phép gán yield cho một biến hay hằng số nào đó trong hàm generator thì phải truyền param vào hàm next (không ứng dụng cho next trước hết), nếu không biến này sẽ có mức giá trị là undefined)

Tóm lại

  • Generator là một trong những phương thức hiệu quả để thao tác với tài liệu collection, song song là cơ sở để xử lý các yêu cầu dị đồng bộ (được ứng dụng trong redux-saga) nếu như bạn muốn biết nó được ứng dụng như nào thì có thể tham khảo nội dung bài viết này nhé

  • Bằng việc sử dụng Generator, lập trình viên có thể phát triển các đoạn mã xử lý yêu cầu bất động bộ một cách đơn giản và rõ ràng hơn. Các câu lệnh yield trong Generator có thể trả về các Promise từ những yêu cầu dị đồng bộ

  • Cấu trúc async/await dựa trên Generator để đơn giản hoá cách xử lý kết quả resolve trả về từ mỗi Promise

  • Trên đây là một số tri thức mình tìm hiểu được về generator function cảm ơn mọi người đã theo dõi

Nguồn tham khảo

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
  • https://blog.daovanhung.com/post/generator-function-trong-javascript

You May Also Like

About the Author: v1000