“Code Tailor “provides technology related information and a series of basic articles for front-end developers. Follow the wechat public account” Rookie of Xiaohe Mountain “to get the latest articles.

preface

Before we start, we want to let you know that this article is a summary of the chapter “Generator” in ECMAScript6 by Yifong Nguyen. If you already know the following, you can skip this section and get to the topic

  • What is a Generator?
  • How to create and use it?
  • How does it work in asynchrony?
  • The advantages and disadvantages

If you are a little bit forgotten about some parts, 👇🏻 is ready for you!

Learning links

The Generator’s study

Asynchronous application of Generator

Summary to summarize

concept

Generator functions are an asynchronous programming solution provided in ES6. Syntactically, the Generator function is a state machine that encapsulates multiple internal states and needs to use the next() function to continue the following code.

Create and use

function* helloWorldGenerator() {
  yield 'hello'
  yield 'world'
  return 'ending'
}
var hw = helloWorldGenerator()
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
Copy the code

Commonly used method

  • Generator.prototype.next()

The next() method returns an object containing the properties done and value. The method can also pass a value to the generator by taking a parameter

The returned object contains two attributes:

  • done(Boolean type)
  • If the iterator exceeds the end of the iteration sequence, the value istrue. In this case,valueOptionally specify the return value of the iterator.
  • If the iterator can generate the next value in the sequencefalse. This is equivalent to not being fully specifieddoneProperties.
  • value– Any returned by the iteratorJavascriptValue. whendoneThe value oftrueYou can ignore this value.
function* gen() {
  yield 1
  yield 2
  yield 3
}

var g = gen() // "Generator { }"
g.next() // "Object { value: 1, done: false }"
g.next() // "Object { value: 2, done: false }"
g.next() // "Object { value: 3, done: false }"
g.next() // "Object { value: undefined, done: true }"
Copy the code
  • Generator.prototype.return()

The return() method returns the given value and terminates the generator

function* gen() {
  yield 1
  yield 2
  yield 3
}
var g = gen()
g.next() // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next() // { value: undefined, done: true }
Copy the code
  • Generator.prototype.throw()

The throw() method is used to throw an exception to the generator and resume the generator’s execution, returning an object with both done and value attributes

  • done(Boolean type)
  • If the iterator has already returned the end of the iteration sequence, the value istrue. In this case, you can specify iteratorsvalueThe return value of.
  • If the iteration continues to produce the next value in the sequence, the value isfalse. This is equivalent to not specifyingdoneProperty value.
  • value– Any returned by the iteratorJavaScriptValue. whendonetrueCan be omitted.
function* gen() {
  while (true) {
    try {
      yield 42
    } catch (e) {
      console.log('Error caught! ')}}}var g = gen()
g.next() // { value: 42, done: false }
g.throw(new Error('Something went wrong')) // "Error caught!"
Copy the code

Application in asynchrony

var readFile = function (name, ms) {
  return new Promise((resolve, reject) = > {
    setTimeout(() = > {
      console.log(name + 'Finished reading')
      resolve()
    }, ms)
  })
}

var gen = function* () {
  console.log('to specify the generator')
  yield readFile('first'.1000)
  yield readFile('second'.2000)
  return 'Done'
}

var g = gen()
var result = g.next()
result.value
  .then(() = > {
    g.next()
  })
  .then(() = > {
    g.next()
  })
Copy the code

The advantages and disadvantages

Advantages:

  • Can control the execution of the function, can cooperatecoFunction library usage

Disadvantages:

  • Process management is not convenient (i.e. when phase 1 and phase 2 are executed)

For more information, please click on JavaScript asynchronous history

The title self-test

What is the yield keyword for Generator functions ()?

  • A: Stop the execution
  • B: Exit function
  • C: Pause execution and wait for the next() method to be called
  • D: Stop the command and resume the command automatically
Answer

Answer: C

Generator functions are called with a pair of parentheses following the function name as normal functions. The difference is that when a Generator function is called, it does not execute, and instead of returning the result of the function’s operation, it returns a pointer to the internal state, which is the Iterator Object described in the previous chapter.

Next, 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 head of the function or where it was last stopped until the next yield expression (or return statement) is encountered. In other words, Generator functions are executed piecewise, yield expressions are paused tokens, and the next method can resume execution.


Ii: The printed result is () after the following code is executed.

function* generator(i) {
  yield i
  yield i * 2
}

const gen = generator(10)

console.log(gen.next().value)
console.log(gen.next().value)
Copy the code
  • A: [0, 10].[10, 20]
  • B: 20.20
  • C: 10.20
  • D: 0, 10 and 10, 20
Answer

Answer: C

Regular functions cannot stop halfway through a call. However, a generator function can “stop” midway through and then pick up where it left off. Each time a generator function encounters the yield keyword, the function generates the value specified after it. Note that in this case, the generator function does not return a value, but rather generates a value.

So first of all, we initialize the function so that I is equal to 10. We call the generator function using the next() method. The first time a generator function is called, I is equal to 10. It encounters the first yield keyword: it produces the value of I. The generator is now “paused”, with 10 logged.

We then call the function again using the next() method. It starts to pick up where it left off, again I equals 10. Now, it encounters the next yield keyword and produces I *2. I is equal to 10, so it returns 10 times 2, which is 20. That’s 10,20.


Iii. The printed result is () after the following code is executed.

function* generatorOne() {
  yield ['a'.'b'.'c']}function* generatorTwo() {
  yield* ['a'.'b'.'c']}const one = generatorOne()
const two = generatorTwo()

console.log(one.next().value)
console.log(two.next().value)
Copy the code
  • A: a and a
  • B: a and undefined
  • C: ['a', 'b', 'c'] and a
  • D: a and ['a', 'b', 'c']
Answer

Answer: C

Using the yield keyword, we produce values in the generator function. Using the yield * keyword, we can generate values from another generator function or from an iterable (for example, an array). In generatorOne, we use the yield keyword to produce the entire array [‘a’, ‘b’, ‘c’]. The next method of an object (one.next(). Value) returns an object whose value is equal to the entire array [‘a’, ‘b’, ‘c’].

console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined
Copy the code

In generatorTwo, we use the yield * keyword. This means that we get an array of iterators [‘a’, ‘b’, ‘c’]. The first value produced is the first value in the array, a, so the first time we call two-.next ().value, we return a. A subsequent call to next() will continue to return b and c until the array call ends.

console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined
Copy the code

ES 6 series Generator, we end here, thank you for your support! Your attention and praise will be the strongest motivation for us to move forward! Thank you!