I want to write JS asynchronously, but I think it’s too big a project. After all, asynchrony involves a lot of things. So let’s generalize. This article is a brief introduction to generator functions.

Generator functions are an asynchronous programming solution provided by ES6. Some people call them generators.

  • It can first be thought of as a state machine that encapsulates multiple internal states.

  • It is also an iterator object generator. Since execution of the Generator returns a traverser object, the traverser object can, in turn, iterate over each state within the Generator.


### Generator function two features

  1. There is an asterisk between the function keyword and the function name. The asterisk position is not specified.


  1. Inside the function body, yield expressions are used to define different internal states


Analyze the Generator with a few examples

Take a look at the difference between a generator and a normal function:

Normal function calls are followed by normal execution.

But…? Generator function modder reaction.


So how do we get it to work?

You need to use the next method.

Returns an traverser object

function *greet() {

       console.log("Hello world!")

       yield 'hello----------yield'

       console.log("Hello world! 111")

       yield 'world----------yield'

       console.log("Hello world! 222")

       return "Hello world!"


let x = greet()

Copy the code
  • 1 next, output to Hello World! That is, it stops before the first yield

  • Two next, output to Hello World! 111, so it stops before the second yield

  • Three next, output to Hello World! 222, don’t know where it stops

  • 4 next, no output, so the third next is finished


This example demonstrates that the generator function returns an iterator that calls the next method to execute the code in the function body. But it stops at yield.

It can be thought of as a state machine that encapsulates multiple internal states. Executing Generator returns an traverser object. Now that “an iterator object is returned” is explained, but what encapsulates the internal state?

Encapsulates multiple internal states

Encapsulates multiple internal states whose states are represented by yield and return.

Every time next runs, it stops at yield. If there is no yield it will run straight to the end. Return (); return ();

So it’s useless for me to write four next calls, because the third one is already finished.

I can also see from the code above that both yield and return have content, and that content can be used as the current state. How can we see that state?

function *greet() {

       yield 'hello----------yield'

       yield 'world----------yield'

       return "Hello world!"


let x = greet()


Copy the code

Simply print x.next() : x.next() returns an object whose value is yield, done is a Boolean, false if the Generator is completed, and true if it is completed.

Now think about this: Yield can only be followed by strings, right? Try something else.

function *greet() {

       yield 1

       yield false

       yield null

       yield undefined

       yield [1.2.3]

       yield {name:'gen'}}let x = greet()


Copy the code

You can see from the following figure:

  • Yield can be followed by any data type, okay

  • When the function runs, undefined is returned without setting return

So let me try a function

function *greet() {


       yield() = >console.log("I'm the arrow function.")

       yield (() = >console.log("I'm the arrow function called."()}))let x = greet()


Copy the code
  • The first next executes before the first yield, and the value in the return value is the content after the first yield.

  • The second next executes before the second yield, and the value in the return value is the content after the second yield.

– Value is undefined because the function after the second yield is called and returns no value

  • The third next executes the entire function, which returns no value –>value is undefined.


The odd question has increased. Don’t you just say yield? The return value is something after yield.

Let y = yield (()=>console.log(y))() throws an error saying I did not declare y. And this is proof that. Call a next method that executes the code after yield, but not the code before yield.

So the internal execution state should look like this: when yield is encountered, the content immediately to the right of yield is executed, the content to the left of yield is not executed, and the content on the next line of yield is not executed.

Yield is a wall. The right and the front of the wall belong to one world. The left and the bottom of the wall belong to one world.

The first yield does not output y, but the second yield does. Which proves what I said above.

But notice that we can print y, but y is undefined, is there a way to make it not undefined?


Sure, the next method can actually pass values. Experiment with the following code

function *foo() {

       var state1 = yield 'hello';


       var state2 = yield 'world';



let f = foo()




Copy the code

Something amazing happened. It outputs 222,333. That is, the values of the second and third next are printed.

If you think about it, it’s not surprising that the first next will only yield to the front and right of the first yield, not to the left state1, let alone assign to it. So some value to the left of yield requires the next argument passed in by next.

An interesting topic

Print two lines. The first line is “Do you love JavaScript?” , the second line is “JavaScript loves you back ❤️”.

function *startGame() {

       const answer = yield "Do you love JavaScript?";

       if(answer ! = ="Yes") {

              return "Oh wow... Guess we're gone here";


       return "JavaScript loves you back ❤️";


const game = startGame();

Copy the code


The answer:

console.log( game.next().value );

// Do you love JavaScript?



// JavaScript loves you back ❤️

Copy the code