We all know that async/await is a syntactic candy based on Promise, which can block our asynchronous operations to give us more control over our asynchronous tasks. So how to implement async await? In the previous chapter we explained generators. The generator will stop at the next yield every time it executes next, so that it blocks not so much as we await it. We can say that we are async and await it

const test=() = >new Promise((resolve,reject) = >
setTimeout(() = >{
    resolve('test')},1000))

async function func(){
   const data= await test()
    console.log(data);
   const data= await test()
    console.log(data);
}
Copy the code

This section of the function can be simulated using the generator, simulated as the following section.

function* func(){
   const data= yield test()
   console.log(data);
   const data= yield test()
   console.log(data); 
}
Copy the code

However, the generator cannot be executed automatically, so it must be executed manually after the iterator is generated and then called next. We can execute the above method manually

const it=func();
const p=it.next();/ / return} {value: Promise, done: false
p.value.then(res= >{
    console.log(res);
    const p2=it.next();
    p2.value.then(res= >{
        console.log(res); })})Copy the code

If we were to yield test() and return resolve, the yield test() method would yield test() and resolve would be undetermined. When the yield test() method is executed, the value would be determined by passing next(val). What does that mean? Look at this code right here

function* func(){
    const ans=yield test();
    console.log(ans);
    const ans2=yield test();
    console.log(ans2);
}

const it=func();
const p=it.next();// return {value:Promise,done:false}, ans does not get resolve
p.value.then(res= >{
    console.log(res);
    const p2=it.next(res); // The value of ans in the code above is determined to be res;
    p2.value.then(res= >{
        console.log(res); })})Copy the code

This code is still executed manually, and we’re not going to get the value for the last yield so how do we modify it to get the value? It’s very simple, just change it a little bit, to a simple recursion.

function autoStart(generator){
        const gen=generator();// Execute the generator function
        function _next(val){
            const p=gen.next(val);
            if(p.done) return p.value;  // End of recursion
            p.then(res= >{
                _next(res); / / recursion
            })
        }
        _next();
}
auto(func);
Copy the code

Above we have basically implemented a simple async/await, and then we are optimizing step by step. First async function returns Promise, and then we need to handle exception, so above we need to return Promise and handle its exception

function autoStart(generator){
    const gen=generator();
    function _next(val){
        return new Promise((resolve,reject) = >{
            try{
                var p=gen.next(val);
                if(p.done) resolve(p.value);
            }catch(err){
                reject(err);
            }
            // Prevent p.value from being the base type
            Promise.resolve(p.value).then(res= >{
                _next(res);
            })
        })
    }
    _next();
}
Copy the code

Finally, let’s try it out with this code

Complete demo

const test =(data) = >new Promise((resolve,reject) = >{
    setTimeout(() = >{ resolve(data); })})function autoStart(generator){
    const gen=generator();
    function _next(val){
        return new Promise((resolve,reject) = >{
            try{
                var p=gen.next(val);
                if(p.done) resolve(p.value);
            }catch(err){
                reject(err);
            }
            // Prevent p.value from being the base type
            Promise.resolve(p.value).then(res= >{
                _next(res);
            })
        })
    }
    _next();
}

function* generator(){
        const data=yield test(1);
        console.log(data);
        console.log(2);
        const data2=yield 3;
        console.log(data2)
        console.log(4);
}
autoStart(generator);
/ / 1
/ / 2
/ / 3
/ / 4
// Perfect output
Copy the code

Refer to the article written async await the minimalist implementation (line 20) | 9 k word Promise/async/Generator principle parsing