一文搞懂async和await的原理

开篇: 以下为我的理解    感觉有帮助的小伙伴点个赞   有啥问题可以评论区一起探讨

阮一峰老师的文章曾经说过async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。其中也提到了async和await的原理就是通过generate生成器和iterator迭代器实现的

在此之前我们应该先去了解一下generate生成器和iterator迭代器

我理解的generate生成器它主要作用就是允许我们对数据进行分段处理,而不是一次性把所有数据全部加载完毕,在实际业务中我们很少或根本就没有用上,因为如果是一些不怎么占用内存的数据也没必要使用生成器,他主要用来处理一些比较大的文件流,或者成千上万条数据时比较有用,分段执行,先拿取要最先使用的数据,再慢慢继续执行,

iterator迭代器 

js中在原型中存在Symbol.iterator属性的都是可迭代对象,可迭代对象最明显的特征就是可以通过

for of 来进行遍历迭代   

HTMLCollection,NodeList ,Map ,Set,String,Array,Arguments等都是可迭代对象

我来举一个更生动的例子

const arr = [1,2,3,4]
const iterator = arr[Symbol.iterator]()
iterator.next()

更加形象了吧,当然symbol.iterator也可以手动加到原型上去,比如将对象变成可迭代的,这个感兴趣的小伙伴可以去试试

生成器和迭代器就讲到这吧,具体的小伙伴可以网上找些视频资料啥的研究研究,接下来才是正题

话不多说,直接附代码+注释:

/**
 * 在此代码中
 * 我们以test模拟接口
 * 以fn为我们的代码逻辑执行函数
 * 以gen为js为我们封装的async 和 await
*/

function test1(str){
    return new Promise((res,rej)=>{
        setTimeout(()=>{
            res(str)
        },3000)
    })
}
function test2(str){
    return new Promise((res,rej)=>{
        setTimeout(()=>{
            res(str)
        },1000)
    })
}
function test3(str){
    return new Promise((res,rej)=>{
        setTimeout(()=>{
            res(str)
        },2000)
    })
}
// async 可以正常执行
// async function fn(){
//     let res1 = await test1('3,1')
//     console.log(res1);
//     let res2 = await test2('2,2')
//     console.log(res2);
//     let res3 = await test3('1,3')
//     console.log(res3);
// }

//假如:js将拥有async前缀的函数改成 generate   await 改成yield
function *fn(a,b,c){
    let res1 = yield test1(a)  // res1的值为下一次next接收的值
    console.log(res1);
    let res2 = yield test2(b)
    console.log(res2);
    let res3 = yield test3(c)
    console.log(res3);
    return res3  //最后一个next return出去
}

//并且内部还封装了一个函数
function gen(fn){
    const iterator = fn('3,1','2,2','1,3') //生成迭代器
    let res;
    const p = new Promise((r)=>{        // 因为使用async为前缀的函数最后都是一个promise
        res = r;                        // p就是最后返回的promise
    })
    // 去遍历每一个迭代对象
    function recursion(val = undefined){
        /**
         * 第一次调用执行test1函数 传值就无所谓了,因为第一次本来就是第一个yield,第一个yield的返回
         * 值是根据下一次next传值定义的,返回done,value,done为false,则执行下面的判断是否为promise,
         * 如果不是则没有异步,直接调用下一次的next,否则等异步执行完成后调用
         * 
         * 第二次执行recursion,再调用next并且传递第一次执行返回的值,这样res1就能接收到返回的结果了
         * 第一个yield res1 返回值为 3,1
         * 执行test2函数,获取到他返回的done和value,也是false,则继续判断是否为promise,并且把value交给第三次next函数
         * 第二个yield res2 返回值为 2,2
         * 第三次执行recursion,基本同上
         * 第三个yield res3 返回值3,1
         * 
         * 第四次执行recursion函数,调用next函数,他发现没有yield了,则只是打印了一下res3的值,返回的done为true,value为
         * return的res3,done为true,则调用res这个成功的函数返回出去
         * 整体流程就这样
         * 不过需要注意的是 每一次调用next,他执行的是要执行到yield哪一行到上一次yield的下面那一行
         * 例如
         * 第一次next执行的是41行
         * 第二次next执行的是42,43行
         * 以此类推
         * 
        */
        const {done,value} = iterator.next(val) //执行yield
        if(done){
            return res(value)
        }
        if(value instanceof Promise){
        value.then((res)=>{
          recursion(res)
        })
        }else{
          recursion(value)
        }
    }
    recursion()
    return p
}

gen(fn).then((res)=>{
    console.log(res); //该then 就可以当作是fn函数的返回值
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值