Skip to content
Home » Generator Function Là Gì | Triển Khai Iterator

Generator Function Là Gì | Triển Khai Iterator

Javascript Generator: Tìm hiểu qua ví dụ đơn giản  😍

Generator function trong javascript

Bài đăng này đã không được cập nhật trong 2 năm

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 kết hợp mạnh mẽ với reactjs, mong mọi người theo dõi

1) Generator function là gì

  • Generator là một tính năng mới của ngôn ngữ 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ý bất đồ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 khi hàm kết thúc, và có thể tiếp tục chạy ở 1 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 đó

  • functionName: là tên của hàm
  • param: là tham số đầu vào
  • statements: là phần code mà ta muốn xử lý

Khi chúng ta gọi Generator function : ” functionName() ” , nó không trả về các kiểu dữ 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 dữ liệu, sau mỗi bước resume lại generator function. Khi đó generator function sẽ thực thi hàm cho đến khi gặp từ khóa yield , hoặc return kế tiếp chưa được duyệt ở bước trước

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

Sơ lược về iterator: Iterator là một bộ duyệt dùng để duyệt qua một mảng, một danh sách 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ề phần tử kế tiếp, đồng thời ghi nhận luôn phần tử đã lặp là phần tử next(). Phương thức next() sẽ return về một Object gồm hai thuộc tính là value và done. done có giá trị true nếu Iteration đã hoàn thành, ngược lại nó 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, ngược lại sẽ trả về true.

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

  • next(): Tiếp tục thực thi hàm cho đến khi 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 (đồng thời 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 2 lần next() sau đó gọi đến return() thì hàm sẽ bị dừng lại 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ẽ được trả ra và generator function sẽ dừng lại và không thực thi nữa

Hai ví dụ trên mình đều có truyền tham số vào cho return() và throw() còn next() thì mình chưa truyền vậy truyền tham 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 tham số cho next()

Hàm next có param truyền vào nó (next(param)) thì param chính là giá trị thay thế của yield đang bị dừng lại trước đó trong hàm generator

Do đó, hàm next đầu tiên dù có truyền param vào cũng bị bỏ qua bởi vì đối với hàm next đầu tiên, vẫn chưa có yield nào đang bị dừng lại. Nghĩa là đối với lời gọi next đầu tiên thì next() = next(undefined) = next(null) = next(true) = next(100) = next(“any string”) = next([]) = next({key: “value”})


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() đầu tiên thì kết quả nhận được là


    value: 100

    và dừng lại ở 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

    nghĩa là

    const i = 5 * (yield 100)

    sẽ trở thành

    const i = 5 * 20

    và i lúc này sẽ có giá trị là

    i = 5 * 20 = 100

    . Giá trị trả về của next(20) là

    (2*100)/4 = 50

    và dừng lại trước

    yield (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ước

    yield j

  • Lần gọi tiếp theo next() mình không có truyền tham 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 chú ý (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 áp dụng cho next đầu tiên), nếu không biến đó sẽ có giá trị là undefined)

kết luận

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

All rights reserved

Generator function và Yield trong javascript

Bài đăng này đã không được cập nhật trong 4 năm

Generator function

Generator function là một trong những chức năng không còn mới đối với lập trình viên Javascript. Từ phiên bản ECMAScript 2015 (ES6) nó đã được nhà phát triển đưa vào sử dụng bằng cú pháp khai báo “function* ” , và tất nhiên là trả về một Generator object.

Đâu đó trên mozilla.org có định nghĩa như sau : “Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances “. Vì thế bạn có thể hiểu rằng nó là một function có thể được thực thi nhiều lần liên tiếp mà ngữ cảnh (số lượng biến, giá trị biến, trạng thái các thành phần bên trong hàm …) đều có thể lưu lại sử dụng sau mỗi phiên. Với chức năng mới này, Generator function cũng có thể dừng thực thi bất cứ thời điểm nào, đợi một điều kiện nào nó xảy ra rồi mới tiếp tục thực thi (Ví dụ như khi gọi ajax, các kiến trúc async chẳng hạn).

Lời Kết

Dưới đây là một map thể hiện mối quan hệ giữa generators và iterators, bởi Axel Rauschmayer trên Exploring ES6.

Generators chính là một cách thực hiện của iterable và nó dựa theo luật của

iterable

của

iterator

. Vì thế mà chúng có thể dùng để tạo ra iterables.

Tính năng tuyệt vời nhất của Generator là khiến execution bị hoãn lại. Với

yield

nếu xài ES6.

Không những thế với

yield*

, ta còn có thể gọi một generator nằm trong một generator khác.

Generators chính là cách thức để giúp việc phát triễn không đồng bộ trở thành đồng bộ.

Nguồn: Topdev via Medium

Đăng nhập/Đăng ký
Danh sách bài
Giới thiệu về Javascript
Giới thiệu
Biến & hằng số
console.log()
Chú thích
let & var
Hàm trong Javascript
Hàm
Phạm vi của biến
Các kiểu dữ liệu cơ bản trong JavaScript
Kiểu dữ liệu
Kiểu dữ liệu số
Toán tử
Symbol
Ép kiểu
Mảng trong Javascript
Mảng
Chuỗi ký tự
Mảng đa chiều
Kiểm soát luồng trong Javascript
Toán tử
if
for
break & continue
switch
for…in
for…of
while
Đệ quy
Đối tượng trong JS
Lớp
Đối tượng
Prototype
Kế thừa
this
Phương thức
Hàm tạo
Getter & Setter
Tham số mặc định
Xử lý ngoại lệ trong JS
Ngoại lệ
throw
Bất đồng bộ trong JS
JSON
Promise
async & await
ES6 trong JS
Giới thiệu JavaScript ES6
Template Literal
Toán tử Spread
Destructuring
Kiến thức nâng cao trong JS
Arrow
Closures
Cơ chế Hoisting
Cú pháp “use strict”
Module
setTimeout()
Callback
setInterval()
Map & WeakMap
Set & WeakSet
Proxy
Ngày & thời gian
Iterator & Iterable
Generator
Regex
Kiểm tra lỗi
Tutorial
JavaScript Tutorial
Trang trước
Trang tiếp theo
Bạn cần
đăng nhập
để bình luận bài viết này
Chưa có bình luận nào, hãy là người đầu tiên bình luận
Chia sẻ kiến thức – Kết nối tương lai
Về chúng tôi
Về chúng tôi
Giới thiệu
Chính sách bảo mật
Điều khoản dịch vụ
Học miễn phí
Học miễn phí
Khóa học
Luyện tập
Cộng đồng
Cộng đồng
Kiến thức
Tin tức
Hỏi đáp
CÔNG TY CỔ PHẦN CÔNG NGHỆ GIÁO DỤC VÀ DỊCH VỤ BRONTOBYTE
The Manor Central Park, đường Nguyễn Xiển, phường Đại Kim, quận Hoàng Mai, TP. Hà Nội
THÔNG TIN LIÊN HỆ
[email protected]
©2024 TEK4.VN
Copyright © 2024
TEK4.VN

Generator là gì? Lý do bạn nên dùng Python Generator

Trong bài viết này, ITNavi sẽ giúp bạn tìm hiểu kỹ lưỡng hơn để xem Generator là gì cũng như lý do nên sử dụng Generator trong Python. Sự khác biệt của Generator với các hàm thông thường như thế nào. Cùng làm rõ tất cả qua các nội dung sau.

Javascript Generator: Tìm hiểu qua ví dụ đơn giản  😍
Javascript Generator: Tìm hiểu qua ví dụ đơn giản 😍

Lý do bạn nên dùng Python Generator là gì?

Tiết kiệm tối đa không gian cho bộ nhớ

Xá iterator khi không tính toán giá trị của từng mục khi khởi tạo thì chúng chỉ tính toán khi bạn yêu cầu. Quá trình này được gọi là lazy evaluation. Lazy evaluation hữu ích khi người dùng có một bộ dữ liệu cực lớn để thực hiện tính toán và nó cho phép bạn có thể sử dụng dữ liệu ngay lập tức kể cả khi bộ dữ liệu đang được tính toán. Iterator chỉ có thể lặp lại được một lần nếu như bạn cứ cố lặp lại primes một lần nữa thì chắc chắn sẽ không có thêm bất kỳ giá trị nào được trả về và điều này tương tự như một danh sách rỗng.

Đơn giản code nên dễ triển khai

Generator hỗ trợ cho code sẽ được triển khai dễ dàng, ngắn gọn hơn so với các lớp iterator tương tự.

Tạo ra các list vô hạn

Generator là một trong những phương tiện rất tuyệt vời giúp bạn tạo ra các luồng dữ liệu vô hạn nhất. Và luồng dữ liệu này bạn không cần phải lưu trữ trong toàn bộ bộ nhớ bởi vì Generator chỉ có thể tạo ra một phần tử theo dạng thời điểm nên có thể biểu thị được luồng dữ liệu một cách vô hạn nhất.

Điểm mạnh Generator mang lại

Generator function cho phép người dùng có thể tạo ra các iterator theo cách đơn giản hơn và nó giới thiệu câu lệnh yield cho Python. Ngoài ra, nó còn hoạt động như return vì nó sẽ thực hiện trả về một giá trị. Khi đó, Generator sẽ giúp bạn tiết kiệm được trạng thái của function và trong lần tiếp theo thì function sẽ được gọi và tiếp tục từ nơi nó dừng lại cùng với các giá trị biến mà nó đã có được trước khi yielding. Đây chính là khả năng mà Python mang lại cho lập trình viên.

Tùy vào nhu cầu thực tế để đưa ra lựa chọn phù hợp nhất

Nói tóm lại thì những ưu điểm nổi bật thuyết phục bạn nên sử dụng Generator sẽ là:

  • Generator cho phép bạn có thể tạo ra iterator dựa theo cách rất pythonic.
  • Iterator sẽ cho phép lazy evaluation và chỉ tạo ra element tiếp theo của một đối tượng. Khi đó, nó sẽ lặp lại khi đạt được các yêu cầu và điều này được cho là hữu ích đối với các bộ dữ liệu có kích thước lớn.
  • Iterator và Generator thường chỉ có thể lặp lại được một lần duy nhất.
  • Generator Function thường sẽ tốt hơn nhiều so với Iterator.
  • Generator Expressions sẽ tốt hơn các Iterator (điều này được tính đối với các trường hợp đơn giản).

Chúng tôi rất vui mừng chia sẻ kiến thức sâu sắc về từ khóa Generator la gi và hy vọng rằng nó sẽ hữu ích cho bạn đọc. Bài viết tập trung trình bày ý nghĩa, vai trò và ứng dụng của từ khóa này trong việc tối ưu hóa nội dung trang web và chiến dịch tiếp thị trực tuyến. Chúng tôi cung cấp các phương pháp tìm kiếm, phân tích và lựa chọn từ khóa phù hợp, cùng với các chiến lược và công cụ hữu ích. Hy vọng rằng thông tin mà chúng tôi chia sẻ sẽ giúp bạn xây dựng chiến lược thành công và thu hút lưu lượng người dùng. Xin chân thành cảm ơn sự quan tâm và hãy tiếp tục theo dõi blog của chúng tôi để cập nhật những kiến thức mới nhất.

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ần số học tên tiếng anh chính xác là gì? Các thuật ngữ phổ biến mà bạn nên biết

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 : Chứng nhận hợp quy là gì? Lợi ích khi doanh nghiệp có giấy chứng nhận hợp quy

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

Cách tạo Generator trong Python đơn giản

Sau khi hiểu được Generator là gì thì chắc hẳn bạn đang thắc mắc về cách tạo Generator trong Python đúng không? Câu trả lời dưới đây sẽ giải đáp cho bạn. Để tạo được Generator trong Python thì bạn dùng từ khó def tương tự với định nghĩa một hàm. Trong Generator, sử dụng câu lệnh yield để trả về một phần tử thay cho câu lệnh return như bình thường khác. Nếu các hàm có chứa ít nhất một yield thì chắc chắn đây đã là một hàm Generator. Với trường hợp này thì cả yield và return sẽ được trả về các giá trị từ ham. Chỉ có điều khác biệt là return sẽ chấm dứt hoàn toàn một hàm còn yield sẽ chỉ tạm dừng lại các trạng thái bên trong hàm rồi sau đó vẫn có thể tiếp tục được ngay khi gọi lần sau. Ví dụ dễ hiểu như sau: khi bạn gọi phương thức _next_() lần thứ nhất thì ngay sau đó Generator sẽ thực hiện các công trình tính toán giá trị rồi gặp các từ khóa yield nào nó sẽ trả ngay các phần từ trở lại vị trí đó. Ngay khi bạn gọi phương thức _next_() lần thứ 2 thì Generator sẽ không bắt đầu chạy tại vị trí đầu tiên mà ngay phía sau từ khóa yield thứ nhất. Cứ như vậy, thì Generator sẽ tạo ra được các phần tử trong dãy cho đến khi không thể gặp được từ khóa yield nào nữa thì sẽ thực hiện giải phóng Stoplteration.

Cách tạo Generator trong Python khá đơn giản

B28 Generator Function trong JavaScript
B28 Generator Function trong JavaScript

Triển khai iterator

Khi muốn triển khai một iterator, chúng ta phải tạo thủ công method

next()

. Vì generator là iterable, nên chúng có thể giúp chúng ta đơn giản hóa việc triển khai iterator.

Mình xin sử dụng ví dụ từ bài viết Iterators và Iterables trong JavaScript:


const obj = { blog: "homiedev.com", categories: ["ReactJS", "JavaScript", "TypeScript"], isFrontEndBlog: true, }; obj[Symbol.iterator] = function () { let i = 0; let values = Object.values(this); return { next: () => { return { value: values[i++], done: i > values.length, }; }, }; };

Bây giờ, chúng ta có thể sử dụng generator để triển khai iterator như sau:


const obj = { blog: "homiedev.com", categories: ["ReactJS", "JavaScript", "TypeScript"], isFrontEndBlog: true, *[Symbol.iterator]() { const values = Object.values(this); for (let index = 0; index < values.length; index++) { const element = values[index]; yield element; } }, }; for (const element of obj) { console.log(element); }

Như các bạn có thể thấy, method

Symbol.iterator

nhìn đơn giản hơn khi chúng ta sử dụng generator.

Kết quả sẽ như sau:


homiedev.com ['ReactJS', 'JavaScript', 'TypeScript'] true

Bằng cách sử dụng generator chúng ta có thể tạo một chức năng quản lý dữ liệu như thêm phần tử vào danh sách, lặp qua những phần tử đã thêm vào danh sách, ví dụ:


class List { constructor() { this.elements = []; } count() { return this.elements.length; } isEmpty() { return this.elements.length === 0; } add(element) { this.elements.push(element); } *[Symbol.iterator]() { for (let element of this.elements) { yield element; } } } let list = new List(); list.add("Homiedev"); list.add("Front-End"); list.add("JavaScript"); for (let item of list) { console.log(item); }

Kết quả:


Homiedev Front-End JavaScript

Như vậy là chúng ta đã tìm hiểu qua generator trong JavaScript. Hi vọng bài viết giúp ích cho các bạn. Chúng ta sẽ gặp lại nhau trong các bài viết sắp tới nhé 😁.

Generators có thể xem như là cách áp dụng của iterables

Điều khiến generators trở nên đặc biệt bởi vì chúng là những functions có khả năng hoãn lại quá trình execution mà vẫn giữ nguyên được context.

Đây là một tính năng rất quan trọng khi ta phải dùng tới những executions đòi hỏi phải có quãng pause nhưng context phải được để nguyên nhằm để recover lại trong tương lai khi cần đến.

Bạn có từng nghe qua quá trình phát triển async chưa?

Syntax – Cú pháp

Syntax (Cú pháp) cho generators bắt đầu với

function*

declaration của chính nó (nhớ lưu ý cái asterisk) và

yield

dành cho khi generator muốn dừng (pause) execution.

function* generator() { // A yield ‘foo’ // B }

Với

next

function, chúng ta có thể kiểm soát được quá trình tạo ra một generator từ

generator

sẵn có.

Khi chạy

next

function, thì code của

generator

sẽ được thực hiện (execute) và cho đến khi gặp

yield

thì sẽ ngừng lại.

Lúc đó,

yield

sẽ xen vào và khiến cho

generator

execution bị đình chỉ (pause).

const g = generator() g.next() // { value: ‘foo’, done: false } // Our generator’s code A gets executed // and our value ‘foo’ gets emitted through yield. // After this, our generator’s execution gets suspended. g.next() // { value: undefined, done: true } // At this stage the remaining code (i.e. B) gets executed. // Because no value is emitted we get ‘undefined’ as the value, // and the iterator returns ‘true’ for iteration done.


yield

được sinh ra cùng lúc với generator và cho phép chúng ta đưa ra các giá trị mà mình muốn. Tuy nhiên, nó chỉ thực hiện được khi ở trong phạm vi của generator.

Nếu thử dùng

yield

với một giá trị trong callback thì cho dù đã declared trong generator thì nó vẫn sẽ bị lỗi.

function* generator() { [‘foo’,’bar’].forEach(e => yield e) // SyntaxError // We can’t use ‘yield’ inside a non-generator function. }

yield*


yield*

được tạo ra nhằm có khả năng gọi một generator nằm trong một generator khác.

function* foo() { yield ‘foo’ } // How would we call ‘foo’ generator inside the ‘bar’ generator? function* bar() { yield ‘bar’ foo() yield ‘bar again’ } const b = bar(); b.next() // { value: ‘bar’, done: false } b.next() // { value: ‘bar again’, done: false } b.next() // { value: undefined, done: true }

Bạn có thể thấy iterator, thuộc

bar

generator, không hề chạy như đúng ý ta khi call

foo

.

Đó là mặc dù

foo

execution cho ra một iterator, nhưng ta sẽ không có lặp lại (iterate) nó được.

Vì thế mà ES6 cần có operator

yield*

function* bar() { yield ‘bar’ yield* foo() yield ‘bar again’ } const b = bar(); b.next() // { value: ‘bar’, done: false } b.next() // { value: ‘foo’, done: false } b.next() // { value: ‘bar again’, done: false } b.next() // { value: undefined, done: true }

Đồng thời nó cũng hoàn toàn có thể áp dụng với data consumers

for (let e of bar()) { console.log(e) // bar // foo // bar again } console.log([…bar()]) // [ ‘bar’, ‘foo’, ‘bar again’ ]


yield*

có khả năng kiểm tra và chạy qua hết tất cả ngõ ngách trong generator để

yield

ra phần nó cần.

function* bar() { yield ‘bar’ for (let e of foo()) { yield e } yield ‘bar again’ }

Generators cũng chính là Iterators

Generators thực chất là những iterables đơn giản. Nói cách khác chúng cũng sẽ theo luật của

iterable



iterator

.

Luật của

iterable

cho ta biết một object sẽ nên return một function itera với key là

Symbol.iterator

.

const g = generator() typeof g[Symbol.iterator] // function

Còn luật của

iterator

cho ta biết iterator nên là một object chỉ tới yếu tố tiếp theo của iteration. Object này phải chứa một function gọi là

next

const iterator = g[Symbol.iterator]() typeof iterator.next // function

Bởi vì generators là iterables nên chúng ta có thể dùng data consumer

for-of

, để iterate (lặp lại) giá trị của generators (values).

for (let e of iterator) { console.log(e) // ‘foo’ }

Return

Chúng ta còn có thể add vào

return

cho generator, thế nhưng

return

sẽ hoạt động hơi khác đi tùy thuộc vào cách generators’ data được iterated.

function* generatorWithReturn() { yield ‘foo’ yield ‘bar’ return ‘done’ } var g = generatorWithReturn() g.next() // { value: ‘foo’, done: false } g.next() // { value: ‘bar’, done: false } g.next() // { value: ‘done’, done: true } g.next() // { value: undefined, done: true }

Khi ta thực hiện iteration bằng tay, sử dụng

next

, sẽ nhận được returned value (i.e.

done

) cũng chính là

value

cuối của iterator object và khi

done

đưa ra kết quả true.

Mặt khác, khi sử dụng defined data consume như

for-of

hoặc

destructuring

thì returned value sẽ bị bỏ qua.

for (let e of g) { console.log(e) // ‘foo’ // ‘bar’ } console.log([…g]) // [ ‘foo’, ‘bar’ ]

yield*

Như bạn đã biết

yield*

được tạo ra nhằm có khả năng gọi một generator nằm trong một generator khác.

Ngoài ra, nó còn cho phép chúng ta lưu trữ value returned bằng executed generator.

function* foo() { yield ‘foo’ return ‘foo done’ } function* bar() { yield ‘bar’ const result = yield* foo() yield result } for (let e of bar()) { console.log(e) // bar // foo // foo done }

Throw

Chúng ta có thể dùng

throw

trong một generator và

next

sẽ truyền exception ra.

Và khi một exception bị đẩy ra, iterator (lặp) sẽ bị phá và state của nó sẽ được set thành

done: true

function* generatorWithThrow() { yield ‘foo’ throw new Error(‘Ups!’) yield ‘bar’ } var g = generatorWithReturn() g.next() // { value: ‘foo’, done: false } g.next() // Error: Ups! g.next() // { value: undefined, done: true }

Generators cũng chính là Data Consumers

Generators ngoài khả năng như một data producers, với

yield

, nó cũng có thể consume data khi dùng

next

.

function* generatorDataConsumer() { // A console.log(‘Ready to consume!’) while (true) { const input = yield; // B console.log(`Got: ${input}`) } }

Có một vài điểm khá thú vị sau đây

// (1) var g = generatorDataConsumer() // (2) g.next() // { value: undefined, done: false } // Ready to consume! // (3) g.next(‘foo’) // { value: undefined, done: false } // Got: foo

Generator Creation (1)

Ở stage này, chúng ta đang tạo ra generator .

Và execution sẽ dừng lại tại điểm .

Next đầu tiên (2)

Execution đầu tiên của

next

giúp cho generator được executed cho tới khi gặp phải

yield

.

Tất cả các giá trị (value) trong stage này khi đi qua

next

sẽ bị lơ đi. Nguyên nhân là vì vẫn chưa có gặp một

yield

nào cả.

Và execution của chúng ta chỉ dừng lại tại điểm khi một value nào đó được đưa ra bởi

yield

.

Next tiếp theo (3)

Lúc này thì value đã đi qua

yield

và như vậy execution sẽ bị ngừng lại.

Hãy dùng Cases

Implement Iterables

Bởi generators là một iterable implementation, khi chúng được tạo ra thì chúng ta cũng sẽ có một iterable object với từng

yield

đại diện cho một giá trị sẽ được đưa ra trên từng iteration. Nói cách khác chúng ta có thể dùng generators để tạo ra iterables.

Ví dụ sau đây sẽ thể hiện generator như là iterable với khả năng lập một dãi các số nguyên cho tới khi nó đạt

max

. Và ta cũng dùng

for-of

để lập những giá trị trên.

Các bạn cũng cần lưu ý rằng

yield

sẽ khiến các execution bị dừng lại tại một điểm và các iteration sẽ khiến cho execution chạy tiếp tại các điểm đó.

function* evenNumbersUntil(max) { for (let value = 0; value <= max; value += 2) { // When ‘value’ is even we want to ‘yield’ it // as our next value in the iteration. if (value % 2 === 0) yield value; } } // We can now user ‘for-of’ to iterate over the values. for (let e of evenNumbersUntil(10)) { console.log(e) // 0 // 2 // 4 // 6 // 8 // 10 }

Asynchronous Code

Ta còn có thể dùng generators với những async code như

promises

.

Tiện thể thì cũng coi như là để giới thiệu về

async/await

trên ES8.

Ví dụ dưới đây cũng sẽ cho ta thấy cách tìm kiếm một JSON file nhờ vào

promises

. Đây là ví dụ của Jake Archibald thuộc developers.google.com.

function fetchStory() { get(‘story.json’) .then(function (response) { return JSON.parse(response) }) .then(function (response) { console.log(‘Yey JSON!’, response) }) }

Nhờ vào co library và một generator, code của chúng ta sẽ nhìn giống như synchronous code.

const fetchStory = co.wrap(function* () { try { const response = yield get(‘story.json’) const text = yield JSON.parse(response) console.log(‘Yey JSON!’, response) } })

Với

async/await

thì nó vẫn sẽ khá giống so với phiên bản trên

async function fetchStory() { try { const response = await get(‘story.json’) const text = await JSON.parse(response) console.log(‘Yey JSON!’, response) } }

Cú pháp


function* name([param[, param[, ... param]]]) { statements }

  • name: tên hàm.
  • param: tham số đầu vào của hàm, tối đa 255 tham số.
  • statements: nội dung của hàm.

Hàm sẽ không được thực thi ngay sau khi gọi, mà thay vào đó generator function trả về iterator, giống như con trỏ trong vòng lặp. Sau khi hàm

next()

của iterator được gọi, generator function sẽ thực thi hàm cho đến khi gặp từ khóa

yield

đầu tiên. Yield sẽ trả về giá trị cho iterator, generator function kết thúc cho đến khi hết giá trị để yield.

LẬP TRÌNH PYTHON CƠ BẢN #22: GENERATOR LÀ GÌ ? (YIELD)
LẬP TRÌNH PYTHON CƠ BẢN #22: GENERATOR LÀ GÌ ? (YIELD)

Generator là gì?

Để một lập trình viên có thể xây dựng được iterator thì việc theo dõi các bước như: triển khai class bằng phương thức inter_()và_next_(), theo dõi những tình trạng ở bên trong, Stopiteration trong trường hợp xảy ra khi không có giá trị được trả về. Generator còn được dùng với mục đích giải quyết tất cả các vấn đề này. Generator là cách đơn giản được dùng để có thể tạo ra iterator. Bạn có thể đơn hiểu đơn giản Generator là gì như sau: Generator là một trong những hàm trả về một đối tượng (iterator) mà ở đó chúng ta có thể lặp lại (một giá trị ở một thời điểm).

Generator là gì?

Ngoài ra, chúng cũng có nhiệm vụ tạo ra đối tượng theo kiểu danh sách, tuy nhiên bạn chỉ có thể phê duyệt nó qua những phần tử generator một lần duy nhất. Bởi vì, Generator không lưu các dữ liệu trong bộ nhớ nên khi lặp lại thì chúng sẽ tạo ra phần tử tiếp theo trong dãy rồi trả về phần tử đó. Bạn có nhu cầu tìm việc Python vui lòng tham khảo bài viết sau: https://itnavi.com.vn/job/python

Giá trị trả về

Khi chúng ta gọi Generator function : ” nameYourFuntion() ” , nó không trả về các kiểu dữ 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 các node dữ liệu sau mỗi bước resume lại generator function. Khi đó generator function sẽ thực thi hàm cho đến khi gặp từ khóa yield , hoặc return kế tiếp chưa được duyệt ở bước trước. P/s : iterator định nghĩa một chuẩn để tạo ra list các giá trị hữu hạn hoặc thậm chí vô hạn. Nó giúp bạn lấy ra giá trị mong muốn khi list kết quả đã được khởi tạo xong toàn bộ.

Yield

  • Yield được sử dụng ở một vài nơi và có vẻ khái niệm cũng hơi khác nhau. Trong ruby, javascript hay làm chỉ định trong laravel framework … mỗi nơi có một định nghĩa và cách sử dụng khác nhau. Ngay cả anh google dich cũng sẽ làm bạn lúng túng về nó, “năng suất” , “bày ra”, “sản sinh” . Tôi nghe thì thấy có vẻ chả liên quan gì lập trình và chả thấy có gì tò mò để tìm hiểu. Tuy nhiên trong javascript thì yeild lại khá dễ hiểu và dễ hình dung nhé.
  • Về cơ bản, yeild là từ khóa dùng để tạm dừng và cũng để tiếp tục việc thực thi bên trong generator function.
Mới đầu năm mà sao thế giới lại thêm hỗn loạn?
Mới đầu năm mà sao thế giới lại thêm hỗn loạn?

Sử dụng


function* generatorFunc(index) { while (index < 2) { yield index++; } } const iterator = generatorFunc(0); console.log(iterator.next()); // log output: {value : 0, done : false} console.log(iterator.next()); // log output: {value : 1, done : false} console.log(iterator.next()); // log output: {value : underfined, done : true}

Như đã đề cập ở trên thì iterator được khởi tạo bằng generatorFunc với index bắt đầu bằng 0. Bạn có thể thấy yeild ở đây, trong ví dụ này chính là một phiên bản khác giống như return vậy. Nó trả về một đối tượng IteratorResult với hai thuộc tính là “value” và “done”.


value : kết quả của biểu thức trả về. done : nhận giá trị false nếu quá trình generator chưa hoàn thành, true nếu ngược lại.

Giá trị của index được giữ lại sau mỗi lần chúng ta gọi next() và tất nhiên là cả ngữ cảnh của hàm generator cũng thế cho đến khi toàn bộ yield, return đã được duyệt qua..

3.Yield*

Yield* là một dạng ủy quyền thực thi. Ở đây, yield* có thể nhúng mã của một generator function ngay sau nó hoặc là ủy quyền trực tiếp cho một iterator object.

Cú pháp :


yield* [[expression]]

expression ở đây trả về iterator object như đã nói, có thể là generator function, hoặc mảng, hoặng string, hoặc list, ….

Ví dụ :


function* g2() { yield 3; yield 4; } function* g1() { yield* [1, 2]; yield* g2(); yield* '56'; yield* Array.from(arguments); } var iterator = g(9, 10); console.log(iterator.next()); // {value: 1, done: false} console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: 3, done: false} console.log(iterator.next()); // {value: 4, done: false} console.log(iterator.next()); // {value: "5", done: false} console.log(iterator.next()); // {value: "6", done: false} console.log(iterator.next()); // {value: 9, done: false} console.log(iterator.next()); // {value: 10, done: false} console.log(iterator.next()); // {value: undefined, done: true}

Bạn có thể sử dụng yield* theo nhiều cách như trên, miễn rằng đằng sau đó trả về một object có kiểu thuộc iterator.

Chú ý : yield* là một biểu thức chứ không phải là một câu lệnh, do đó nó sẽ phản ánh lại giá trị được return về. Ví dụ :


function* g2() { yield* [1, 2]; return 't sẽ trở thành vua hải tặc, vd như vậy xem chạy ko'; } var rs; function* g() { rs = yield* g2(); } var iterator = g(); console.log(iterator.next()); // {value: 1, done: false} console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: undefined, done: true}, // g2() đã trả về {value: 't sẽ trở thành vua hải tặc, vd như vậy xem chạy ko', don

All rights reserved

function* và yield trong Javascript generator function

Một trong những chức năng, cũng như vấn đề mà mọi developer javascript/nodejs đều gặp phải là lập trình bất đồng bộ (async) và callback hell khó điều khiển.

May thay, function* là một trong những chức năng mới của Javascript trong ECMAScript 2015 (6th Edition, hay tắt là ES6). function* giúp khai báo 1 generator function, trả về 1 Generator object. Với chức năng mới này, hàm có thể dừng thực thi bất cứ thời điểm nào, đợi async chạy xong, xong tiếp tục thực thi.

JavaScript Generators

Như chúng ta đã biết, một function thông thường trong JavaScript không thể tạm dừng giữa chừng và sau đó tiếp tục tại nơi nó đã tạm dừng.

Ví dụ:


function display() { console.log('Đây là'); console.log('blog'); console.log('homiedev.com'); }

Ở ví dụ này, hàm

display()

thực thi từ trên xuống. Cách để thoát

display()

là sử dụng return hoặc đưa ra một lỗi. Nếu chúng ta gọi lại hàm

display()

, nó sẽ bắt đầu thực thi từ trên xuống.


display();

Kết quả:


Đây là blog homiedev.com

Vậy làm thế nào để tạm dừng một hàm và sau đó tiếp tục tại nơi nó đã tạm dừng?

ES6 giới thiệu một loại hàm mới khác với một hàm thông thường gọi là function generator hoặc generator. Sử dụng hàm này, chúng ta có thể tạm dừng và tiếp tục tại nơi đã tạm dừng. Một generator được sử dụng như ví dụ sau:


function* goGroceryShopping() { console.log('Dừng lại lần 1'); yield 'hamburger - 🍔'; console.log('Dừng lại lần 2'); yield 'meat - 🥩'; }

Ở hàm

goGroceryShopping()

:

  1. Đầu tiên, chúng ta sử dụng dấu hoa thị (*) sau

    function

    keyword. Dấu hoa thị biểu thị rằng

    goGroceryShopping()

    là một generator, không phải là một hàm thông thường.
  2. Sử dụng câu lệnh yield trả về một giá trị và tạm dừng việc thực thi hàm.

Bây giờ ta thử gọi hàm

goGroceryShopping()

nhé:


let gen = goGroceryShopping();

Ở đoạn code trên, đầu tiên chúng ta sẽ thấy không có gì ở

console

. Nếu

goGroceryShopping()

là một hàm thông thường thì chúng ta sẽ thấy dữ liệu hiển thị ở

console

.

Chúng ta đã thực thi hàm

goGroceryShopping()

, lúc này giá trị trả về từ hàm này sẽ được gán cho biến

gen

, cùng xem kết quả trả về là gì nhé.


console.log(gen);

Kết quả:


Generator { }

Trong ví dụ này, generator trả về một object Generator mà không thực thi phần thân của nó khi nó được gọi.

Object Generator trả về một object khác có hai thuộc tính (properties) là:

done



value

. Nói cách khác, object Generator là iterable.

Để tìm hiểu về iterable và những thứ liên quan, bạn đọc bài viết: Iterators và Iterables trong JavaScript bạn đã biết chưa?.

Bây giờ chúng ta thử sử dụng method

next()

của object Generator.


let result = gen.next(); console.log(result);

Kết quả:


Dừng lại lần 1 {value: 'hamburger - 🍔', done: false}

Chúng ta có thể thấy, object Generator thực thi phần thân của nó, sau đó hiển thị thông báo

'Dừng lại lần 1'

ở dòng 1 và trả về giá trị

'hamburger - 🍔'

ở dòng 2.

Câu lệnh yield trả về

'hamburger - 🍔'

và tạm dừng generator ở dòng 2.

Tương tự, chúng ta sẽ gọi method

next()

của Generator lần thứ hai:


result = gen.next(); console.log(result);

Kết quả:


Dừng lại lần 2 {value: 'meat - 🥩', done: false}

Lần này Generator tiếp tục thực thi từ dòng 3 và hiển thị thông báo

'Dừng lại lần 2'

và trả về

'meat - 🥩'

.

Ở lần gọi thứ 3, ta sẽ nhận được kết quả:


{value: undefined, done: true}

Vì generator là iterable, chúng ta có thể sử dụng vòng lặp

for ... of

:


for (const element of gen) { console.log(element); }

Kết quả chúng ta nhận được:


Dừng lại lần 1 hamburger - 🍔 Dừng lại lần 2 meat - 🥩

Một ví dụ khác sử dụng generator:


function* infinite() { let index = 0; while (true) { yield index++; } } const generator = infinite(); console.log(generator.next().value); // 0 console.log(generator.next().value); // 1 console.log(generator.next().value); // 2

Ở ví dụ này, mỗi khi chúng ta gọi method

next()

, nó sẽ trả về số tiếp theo. Chi tiết về vòng lặp while bạn đọc tại: Vòng lặp while trong JavaScript.

127. Redux-Saga: Generator Function P1
127. Redux-Saga: Generator Function P1

Ví dụ

Nói thì dông dài, ví dụ sau sẽ dễ hiểu hơn. Hàm sau có tác dụng tạo ra ID tăng dần, mỗi khi hàm next được gọi.


function* id_maker() { var index = 0; while (index < 3) yield index++; } var gen = id_maker(); console.log(gen.next().value); // 0 console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 console.log(gen.next().value); // undefined


yield

sẽ được gọi 3 lần trong vòng lặp for, do đó khi gọi đến lần thứ 4 thì log sẽ trả về undefined.

Ở ví dụ trên,

gen.next()

sẽ trả về một object có 2 tham số là

value



done

. Kiểm tra có còn

next()

được nữa hay không thì chỉ cần kiểm tra giá trị

done


console.log(gen.next()); // { value: 0, done: false }


yield

chỉ có thể return về giá trị, để return về 1 hàm khác, ta sử dụng

yield*


function* anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3; } function* generator(i) { yield i; yield* anotherGenerator(i); yield i + 10; } var gen = generator(10); console.log(gen.next().value); // 10 console.log(gen.next().value); // 11 console.log(gen.next().value); // 12 console.log(gen.next().value); // 13 console.log(gen.next().value); // 20

Kết

Generator function là một trong những tính năng cực kì hữu ích trong ES6. Nodejs có module co và framework koa (được xem là next generator framework for nodejs) tận dụng rất tốt chức năng này.

yield còn dùng để khử callback phức tạp của Javascript, khử promise – hiện còn làm nhiều bạn lúng túng khi mới bắt đầu với nodejs. Tôi sẽ viết 1 bài hướng dẫn sau.
Từ bản nodejs 0.12 trở lên đã được hỗ trợ chức năng generator function,với node v0.12 phải có tham số

--harmony

để có thể sử dụng yield/function*, còn node 4.0 trở lên thì không cần.


node --harmony ./app.js

Tham khảo:

Cảm ơn bạn!

JavaScript generators là gì? Tìm hiểu thông qua ví dụ

Chào các bạn, hôm nay chúng ta lại tiếp tục với các bài viết về học JavaScript cơ bản nhé 😄. Ở bài viết trước chúng ta đã tìm hiểu về Iterators và Iterables trong JavaScript. Trong bài viết này, chúng ta sẽ học về generators trong JavaScript và làm thế nào để sử dụng chúng nhé!

Learn JavaScript Generators In 12 Minutes
Learn JavaScript Generators In 12 Minutes

Keywords searched by users: generator function là gì

Máy Phát Xung Là Gì? Hướng Dẫn Sử Dụng – Đồng Hồ Vạn Năng
Máy Phát Xung Là Gì? Hướng Dẫn Sử Dụng – Đồng Hồ Vạn Năng
Generator Function Trong Javascript
Generator Function Trong Javascript
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản - Youtube
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản – Youtube
Generator Là Gì? Lý Do Bạn Nên Dùng Python Generator
Generator Là Gì? Lý Do Bạn Nên Dùng Python Generator
Thắc Mắc Về Cơ Chế Generator Function Js - Programming - Dạy Nhau Học
Thắc Mắc Về Cơ Chế Generator Function Js – Programming – Dạy Nhau Học
Hiểu Về Php Generators
Hiểu Về Php Generators
Generator Là Gì? Lý Do Bạn Nên Dùng Python Generator
Generator Là Gì? Lý Do Bạn Nên Dùng Python Generator
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản 😍 - Youtube
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản 😍 – Youtube
Function Trong Javascript (Phần 1) - Khái Niệm Về Function | How Kteam
Function Trong Javascript (Phần 1) – Khái Niệm Về Function | How Kteam
Định Nghĩa Hàm Javascript - 3 Cách Cơ Bản Nhất - Vntalking
Định Nghĩa Hàm Javascript – 3 Cách Cơ Bản Nhất – Vntalking
Cùng Khám Phá Sức Mạnh Của Es6 Generators | Topdev
Cùng Khám Phá Sức Mạnh Của Es6 Generators | Topdev
Chức Năng Máy Phát Xung? Nên Mua Máy Phát Xung Nào (2023)
Chức Năng Máy Phát Xung? Nên Mua Máy Phát Xung Nào (2023)
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản 😍 - Youtube
Javascript Generator: Tìm Hiểu Qua Ví Dụ Đơn Giản 😍 – Youtube
Mọi Thứ Về Redux Saga Cho Người Mới Bắt Đầu
Mọi Thứ Về Redux Saga Cho Người Mới Bắt Đầu
Tại Sao Bạn Nên Sử Dụng Python Generator | Topdev
Tại Sao Bạn Nên Sử Dụng Python Generator | Topdev
Hiểu Arrow Function Và This Trong Javascript: Tạo Ra Những Hàm Mạnh Mẽ Với  Cú Pháp Ngắn Gọn - Hướng Dẫn Đầy Đủ Cho Người Mới Bắt Đầu ( Important ) -
Hiểu Arrow Function Và This Trong Javascript: Tạo Ra Những Hàm Mạnh Mẽ Với Cú Pháp Ngắn Gọn – Hướng Dẫn Đầy Đủ Cho Người Mới Bắt Đầu ( Important ) –
Iterator Và Generator - Giải Mã Từ A - Z Iterator Và Generator Trong Python
Iterator Và Generator – Giải Mã Từ A – Z Iterator Và Generator Trong Python
Redux Là Gì? Cách Triển Khai Redux Vào Trong Ứng Dụng React
Redux Là Gì? Cách Triển Khai Redux Vào Trong Ứng Dụng React
Khái Niệm Cơ Bản Về Event Driven Programming | Cppdeveloper
Khái Niệm Cơ Bản Về Event Driven Programming | Cppdeveloper

See more here: kientrucannam.vn

Leave a Reply

Your email address will not be published. Required fields are marked *