Talk about generators

Create a generator


function * gen(){};
function *gen(){};
function* gen(){};

Copy the code

The above is the basic way to write a generator, adding an * to the declaration of the function; If you call this generator function; It returns an iterator; An iterator is an object that has a property called Next and whose value is a function;

Iterators

When we call the generator, we return an iterator. The iterator is an object that contains a method called next. When we call this method, we receive an object like {value: value,done: finished state}. Represents the value obtained, and whether to end the iteration;

function *gen(){
  yield 1;
  yield 2;
};

 let itor = gen();
 itor.next()  // {value:1 , done :false}
 itor.next()  // {value:2 , done :false}
 itor.next()  // {value:undefined , done :true}
Copy the code

The code above shows that the iterator is finished after three calls; Because done is already true; It’s over.

Yield is a keyword that says the program is going to be paused at this point; The pointer moves to the right of the first yield after the first call to next(); Next () returns the value to the right of the first yield; But nothing to the left of yield or after it is executed, and any arguments passed to next() the first time are useless; The next() function is called a second time, executing the content to the left of the first yield and the content after it, and moving the pointer to the right of the second yield and returning the content to the right of the second yield to value; To carry on sequentially;

3. Implement an async function;

Implement an await and async effect using the gen function;

How to achieve the effect of an async function, we know that await can block the execution of subsequent code, and only after the result of the former await will be executed, so we can also control the timing of executing the next function to achieve this effect. Take a look at the code;



let getValue = function (url) {
  return new Promise(resolve= > {
    console.log(url);
    setTimeout(() = > {
      resolve(url);
    }, 1000)})}// define an asynchronous function;
function* gen () {
  yield getValue('1')
  yield getValue('2')
  yield getValue('3')
  yield getValue('4')
  yield getValue('5')}Copy the code

On the basis of the above code, we can think about how to achieve such an effect one by one; Because as normal, we need to call the next function one by one to get the result; So when to call the next function is the key; To achieve the effect of one equal to another, we need to call it when the last getValue() result returns; So you can implement the following code;

function co (gen) {
  let itor = gen();
  function next (data) {
    let res = itor.next(data);
    if (res.done) {
      return res.value;
    }
    res.value.then(data= > {
      next(data)
    })
  }

  next()
}


co(gen)

Copy the code

The principle of async and await is essentially a gen() function with an asynchronous scheduler; This is the co function;