How do you make generator functions run sequentially and automatically instead of using.next() one at a time to advance?

Js write function writing method

  1. Common function
  2. Constructor method on the prototype chain
  3. Anonymous functions (function expressions)
  4. Execute function immediately
  5. Recursive function
  6. Higher-order functions
  7. Functions as methods of objects
  8. The callback
  9. async
  10. closure
  11. Arrow function
  12. Generator function

What is a generator function?

Common function

function listPeople() {}Copy the code

Adding an asterisk becomes a generator function

function* listPeople() { 
    let i = 0; 
    yield i; / / stop
    i++; 
    yield; 
    i++; 
    yield i; 
}
Copy the code
const people = listPeople();
Copy the code

People is like an iterator

console.log(people.next());
console.log(people.next());
console.log(people.next());
console.log(people.next());
Copy the code

Top priority!!

Every.next(), which essentially means that we execute a yield statement once and yield returns an object (the value of the number following yield and done) and points to the next yield (as I understand it). Value is the value of the argument after yield, and done is to see if the function is finished

Done will change to true until the end of execution

Here’s another example:

const inventors = [
    { first: 'Alert'.last: 'Einstein'.year: 1879 },
    { first: 'Isaac'.last: 'Newton'.year: 1643 },
    { first: 'Galileo'.last: 'Galilei'.year: 1564 },
    { first: 'Marie'.last: 'Gurie'.year: 1867 },
    { first: 'Johannes'.last: 'Kapler'.year: 1571 },
    { first: 'Nicolaus'.last: 'Copernicus'.year: 1473 },
    { first: 'Max'.last: 'Planck'.year: 1858}]function* loop(arr) { // Generator
    // console.log(arr);
    for (const item of arr) {
        yielditem; }}const inventorGen = loop(inventors);
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
console.log(inventorGen.next());
Copy the code

Now we need to write next so it will run, so how can we make it run automatically?

Let’s look at the following example

function* steps() {
    console.log('fetching beers');
    const beers = yield ajax('http://api.react.beer/v2/search? q=hops&type=beer');
    console.log(beers, The '-');

    console.log('fetching wes');
    const wes = yield ajax('http://api.github.com/users/wesbos');
    console.log(wes, The '-');

    console.log('fetching fat joe');
    const fatJoe = yield ajax('https://api.discogs.com/artists/51980');
    console.log(fatJoe, The '-');
}

const dataGen = steps();
dataGen.next();
Copy the code

At this point, we need to add ajax functions

// This function is a promise function because it has fetch
function ajax(url) {
    fetch(url)
        .then(data= > data.json())
        .then(data= > dataGen.next(data))
}
Copy the code

For this code, let’s understand it first

fetch(url)
    .then(data= > data.json())
    .then(data= > dataGen.next(data))
Copy the code

The FETCH first passes the URL address, which extracts the resource from the specified URL, and then gives data all the data.

.then(data= >Data.json ()) is equivalent to.then(data){return data.json(); 
}
所以
.then(data= >Datagen.next (data)) is equivalent to.then(data.json){return dataGen.next(data.json()); 
}
Copy the code

Then beers will get the result of the previous.then, i.e. Data.json ()

I don’t know if you have any questions, but I do

The next (…). Json (), why datagen.next (…) And the return value of?

I started looking for information and found it in Generator in ES6!

The yield expression itself returns no value, or always returns undefined. The next method can take an argument that is treated as the return value of the previous yield expression.

Let’s look at an example

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}
/ / in case 1
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
/ / case 2
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
Copy the code

In case 1, the first run of the next method yields 6, but since the second run of the next method takes no arguments, undefined is returned for yield (x + 1), so NaN is returned after 2 * undefined, and so on.

In case 2, the first run of the next method yields a result of 6, but since the second run of the next method provides arguments that yield (x + 1) = 12 and yield (y / 3) = 13, So x is 5, y is 24, z is 13. It returns 42.


All right, now let’s move on

This function doesn’t work. Why is that? Because Fetch is not currently supported by Node

So we should make it run in the browser to create index.html

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <script src="./4.js"></script>
</body>
</html>
Copy the code

run

Success!