Friends who need the Source version of Promise: Send links

This article focuses on the relationship between (iterator) and the use of generator */yield, as well as the use of async/await, a higher-spec version of generator.

Outline:

  • Iterators
  • The generator*/yield
  • Asynchronous version generatorasync/await

Iterators

Take a look at the word “iteration.” What does it mean? Each iteration of the “process” is called an iteration. However, iteration preserves the results, that is, each iteration starts the next iteration based on the results of the previous iteration. For example, the word iteration is often used in product development. Every cycle involves iterative product development, but it is not possible to build a product from scratch every time, it is definitely based on the previous version of the product, that is, iteration.

From this we can sort out two key points about iteration:

  • The process is repetitive
  • Returns the result of the last iteration

So what is the concept of “iterator” in JS?

Look at the concept in MDN: transport address

An iterator in JS is an array object that calls next over and over again, returning a result each time. When there’s nothing left to return to, it stops. So next’s return object has two properties done and value. Done indicates whether it is finished, and value indicates the result of the current iteration. When done is true, the iteration is over, and no result is returned, i.e., no value attribute.

Iterators, however, have a set of specifications:

Look at the concept in MDN: transport address

The iterator

  • Iterators are what we discussed abovenextMethod, returndoneandvalue(done:trueYou can omit) two parameters.
function iteratorFunc() {let arr=[...arguments]
    let nIndex=0
    return {
        next:()=>{
            return nIndex<arr.length?
            {value:arr[nIndex++],done:false}, {done:true}}}}letA = iteratorFunc (1, 2, 3) the console. The log (a.n ext ()) / / {done:false,value:1}
console.log(a.next())//{done:false,value:2}
console.log(a.next())//{done:false,value:3}
console.log(a.next())//{done:true}
Copy the code

Iterable “object”

  • In terms of iterable “objects”, we need to implement on objects@@iteratorThe method, which is equal to[Symbol.iterator]Returns a custom iteration method to indicate that the object is iterable. Some JS built-in objects are iterable, such as String and Array.

Built-in iterable examples:

let str="I am the iterator of joy."
let b=str[Symbol.iterator]()
console.log(b.next())//{value: "我".done: false}
console.log(b.next())//{value: "Yes".done: false}
console.log(b.next())//{value: "Huan".done: false}
Copy the code

Isn’t it amazing? After so many strings, there is still this operation. Its effect is equivalent to the custom iterative method above. So let’s write a custom iteration method:

str[Symbol.iterator] = function() {
    return { // this is the iterator object, returning a single element, the string "bye"
      next: function() {
        this._index += 2
        if (this._index<str.length) {
          return { value: str[this._index], done: false };
        } else {
          return { done: true };
        }
      },
      _index:-2
    };
};
let c=str[Symbol.iterator]()
console.log(c.next())//{value: "我".done: false}
console.log(c.next())//{value: "Huan".done: false}
console.log(c.next())//{value: "The".done: false}
console.log(c.next())//{value: "Generations".done: false}
console.log(c.next())//{done: true}
Copy the code

The iterator I wrote here is to return an alternate character. Run successfully ~yeah~

Generator

Writing iterators is still too convoluting, so generators come along to help us create the existence of iterators.

function * g() {}let it= g()
console.log(it.next())//{value: undefined, done: true}
Copy the code

See any familiar structures! {value: undefined, done: true} * * * * * * * * * * * *

Let’s rewrite the iterator for the string above:

str[Symbol.iterator]= function* () {let index=-2;
    while(index<this.length){
        index += 2
        yield this[index]
    }
}
let kk=str[Symbol.iterator]()
console.log(kk.next())//{value: "我".done: false}
console.log(kk.next())//{value: "Huan".done: false}
console.log(kk.next())//{value: "The".done: false}
console.log(kk.next())//{value: "Generations".done: false}
Copy the code

It’s a lot easier.

Let’s take a look at generators with a few questions:

  • yieldWhat is the return value of?
  • Order of execution?

Example code:

function * gy(){
    console.log("zero")
    let fisrt=yield "first"
    console.log("fisrt",fisrt)
    let second=yield "first"
    console.log("second",second)
}
let ity= gy()
Copy the code

The first time I execute ity. Next (), I print only zero

The second execution of ity. Next () prints only first undefined

Ity. Next (“third”) prints only second third

This shows that each time next stops at yield. Yield returns the value of the current ity. Next (value).

async/await

Let’s see what we can do with the iterator for the Promise object. That is, each iterator is asynchronous.

function setTime(value,id){
    return new Promise((r,j)=>setTimeout(() => {
        console.log(value)
        r(id)
    }, 10))
}
function *a() {let r1 = yield setTime("first",1)
    console.log(r1)
    let r2 =yield setTime("second",2)
    console.log(r2)
    let r3 =yield setTime("third",3)
    console.log(r3)
}
let k=a();
new Promise((resolve,reject)=>{
    function next(data){
        let {value,done}= k.ext (data) // k.ext () returns a promise, so you canthen
        if(!done){
            value.then((data)=>{
                console.log(data)
                next(data)
            })
        }
    }
    next();
})
Copy the code

Since each is asynchronous, we need to process it twice, at which point async/await can come out. Just change */yield seamlessly to async/await.

async function a() {
    let r1 = await setTime("first",1)
    console.log(r1)
    let r2 = await setTime("second",2)
    console.log(r2)
    let r3 = await setTime("third",3)
    console.log(r3)
}
a()
Copy the code