Learning ES6 Series: Basic Understanding and Use of generator

Ask yourself a few more questions each day about why, and you will always get unexpected results. A copyer for beginners


Preface

Today is the second day of National Day, come back home, or be bored, or write code. After all, the code is small and white, there is still a lot to learn, come on!

Recently I was learning redux-saga as a middleware. The principle of its internal code is the generator in ES6, but what about it? I am a little unfamiliar with the generator in ES6 or do not understand it very well, so let's learn the basic grammar first.

Many of them are excerpts from the explanation of ES6 by Ruan Yifeng (all identified as references)


Basic Understanding

The Generator function is an asynchronous programming solution provided by ES6, and its syntax behavior is completely different from that of traditional functions.

Simple understanding:

The Generator function is a state machine that encapsulates multiple internal states.

Executing the Generator function returns a traverser object, that is, the Generator function is a traverser object generation function as well as a state machine. The returned traverser object can iterate through each state within the Generator function in turn


Basic definition of generator function

function * foo(x, y) { ··· }
function *foo(x, y) { ··· }
function* foo(x, y) { ··· }
function*foo(x, y) { ··· }

However, a third type of comparison is recommended because in some vscode plug-ins, formatting is done as a third.


Basic Instances

function * foo() {
    yield 'james'
    yield 'kobe'
}
let it = foo()
console.log(it);
  • Call a function, foo() like a normal function
  • Return object: A pointer object traverser object pointing to the internal state (Iterator Object)

To get the state inside a function, you must call the next() method of the traverser object

The next method of the traverser object must be called to move the pointer to the next state. That is, each time the next method is called, the internal pointer executes from the function header or where it last stopped until the next yield expression (or return statement) is encountered.

it.next()
// { value: 'james', done: false }

it.next()
// { value: 'kobe', done: false }

it.next()
// { value: undefined, done: true }

You can see from above

From the code above, you can see that the generator function above has three states, so you need to call next() three times.


Execution order of generator function

If you want the last value, not undefined, return a value.


next's parameters

  • The yield expression itself does not return a value, or it always returns undefined.

  • The next method can take a parameter that is treated as the return value of the previous yield expression.

Without parameters

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

let a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}

The first next:value is 6

The return value of the second next:yield undefined, y = 2 * undefined, y = NaN, value is undefined

Third next: y, z are undefined, value is undefined


Case with parameters

let b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }

The first next:value is 6

Second next: y = 2 * 12, y = 24, value 8

Third next: yield returns 13, y = 24, z = 13, x = 5, value 42


The combination of generator function and promise

function* foo() {
    const result = yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('hello world')
        }, 3000)
    })
    console.log(result);
}

const it = foo()
it.next().value.then(res => {
    it.next(res)
})

Phenomenon: Asynchronous code is synchronous, that is, result code is synchronous

Code parsing

// Returns a traverser object
it.next()

// Get the promise object
it.next().value

// Get asynchronous resolve results res
it.next().value.then(res => { ... })

// Pass res to the second next, return out
it.next().value.then(res => {
    it.next(rex)
})

such res Is the latest code

epilogue

That's roughly how generator is used, so it's still a good idea to see.

Learning makes me happy.

Keywords: ECMAScript

Added by Mirge on Sat, 02 Oct 2021 19:16:32 +0300