【JS中如何实现异步模式】对async/await的理解,内部原

2020-06-21  本文已影响0人  Allan要做活神仙

有很多,如:

下面来好好讲讲常用的Promise、async/await这些:

回调函数 -> Promise -> generator/yield -> async/await

async 是Generator函数的语法糖,并对Generator函数进行了改进

async 就是将 Generator 函数和自栋执行器,封装在一个函数中。

async function fn() {
  // ...
}

//  等价于

function fn() {
  return spawn(function * () { // spawn  是自执行器
    // ...
  })
}

spawn [spɔːn] n. 卵;菌丝;产物

function spawn(genF){
    return new Promise((resolve, reject)=>{
        const gen = genF() // 先将Generator函数执行下,拿到遍历器对象

        // 声明step
        function step(nextF) {
            let next
            try {
                next = nextF()
            } catch(e){
                return reject(e)
            }
            if(next.done){
                return resolve(next.value)
            }
            Promise.resolve(next.value).then((v)=>{
                step(()=>{return gen.next(v)})
            }, (e)=>{
                step(()=>{return gen.throw(e)})
            })
        };
        
        // 自执行
        step(()=> {return gen.next(undefinex)})
    })
}

关于Generator

Generator 与上下文

Generator 函数, 它执行产生的上下文环境,一旦遇到yield命令,就会暂时退出堆栈,但是并不消失,里面的所有变量和对象会冻结在当前状态。等到对它执行next命令时,这个上下文环境又会重新加入调用栈,冻结的变量和对象恢复执行。

Generator 的实现

具体请参考alloyteam的文章

js 的 Generator 并非由引擎从底层提供额外的支持,而是通过代码的编写,来实现的函数暂停、按序执行。 在实现 Generator 过程中有两个关键点,一是要保存函数的上下文信息,二是实现一个完善的迭代方法,使得多个 yield 表达式按序执行,从而实现生成器的特性。 大体上就是使用由 switch case 组成的状态机模型中, 除此之外,利用闭包技巧,保存生成器函数上下文信息。

Regenerator 通过工具函数将生成器函数包装,为其添加如 next/return 等方法。同时也对返回的生成器对象进行包装,使得对 next 等方法的调用,最终进入由 switch case 组成的 状态机 模型中。除此之外,利用闭包 技巧,保存生成器函数上下文信息。

上述过程与 C#中 yield 关键字的实现原理基本一致,都采用了编译转换思路,运用状态机模型,同时 保存函数上下文信息 ,最终实现了新的 yield 关键字带来的新的语言特性。

Generator 关键:1、通过闭包保存上下文;2、通过 switch/case 组成状态机

上一篇 下一篇

猜你喜欢

热点阅读