asyncToGenerator 實現

shijf 發表於 2021-04-07

摘自 blog.csdn.net/weixin_33826897/arti...


const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000))

function * testG() {

    // await被編譯成了

    const data = yield getData()

    console.log('data: ', data);  

    const data2 = yield getData()  

    console.log('data2: ', data2);  

    return 'success'

}

function asyncToGenerator(generatorFunc) {  

    // 返回的是一個新的函式

      return function() {

        // 先呼叫generator函式 生成迭代器

        // 對應 var gen = testG()

        const gen = generatorFunc.apply(this, arguments)

        // 返回一個promise 因為外部是用.then的方式 或者await的方式去使用這個函式的返回值的

        // var test = asyncToGenerator(testG)

        // test().then(res => console.log(res))    

        return new Promise((resolve, reject) => {          

            // 內部定義一個step函式 用來一步一步的跨過yield的阻礙      

            // key有next和throw兩種取值,分別對應了gen的next和throw方法      

            // arg引數則是用來把promise resolve出來的值交給下一個yield      

            function step(key, arg) {        

                let generatorResult                

                // 這個方法需要包裹在try catch中        

                // 如果報錯了 就把promise給reject掉 外部通過.catch可以獲取到錯誤        

                try {          

                    generatorResult = gen[key](arg)        

                } catch (error) {          

                    return reject(error)        

                }        

                // gen.next() 得到的結果是一個 { value, done } 的結構        

                const { value, done } = generatorResult        

                if (done) {

                    // 如果已經完成了 就直接resolve這個promise          

                    // 這個done是在最後一次呼叫next後才會為true          

                    // 以本文的例子來說 此時的結果是 { done: true, value: 'success' }          

                    // 這個value也就是generator函式最後的返回值          

                    return resolve(value)        

                } else {

                    // 除了最後結束的時候外,每次呼叫gen.next()          

                    // 其實是返回 { value: Promise, done: false } 的結構,          

                    // 這裡要注意的是Promise.resolve可以接受一個promise為引數          

                    // 並且這個promise引數被resolve的時候,這個then才會被呼叫          

                    return Promise.resolve(     

                        // 這個value對應的是yield後面的promise            

                        value          

                        ).then(            

                            // value這個promise被resove的時候,就會執行next            

                            // 並且只要done不是true的時候 就會遞迴的往下解開promise            

                            // 對應

                            //  gen.next().value.then(value => {            

                            //    gen.next(value).value.then(value2 => {            

                            //       gen.next()            

                            //            

                            //      

                            // 此時done為true了 整個promise被resolve了           

                            //      

                            // 最外部的test().then(res => console.log(res))的then就開始執行了            

                            //    })            

                            // })           

                        function onResolve(val) {              

                            step("next", val)      

                        },            

                        // 如果promise被reject了 就再次進入step函式            

                        // 不同的是,這次的try catch中呼叫的是gen.throw(err)            

                        // 那麼自然就被catch到 然後把promise給reject掉啦            

                        function onReject(err) {              

                            step("throw", err)            

                        },)        

                    }      

                }      

                step("next")

            })  

        }}

var test = asyncToGenerator(testG)

test().then((res) => {

    console.log(res);

})
本作品採用《CC 協議》,轉載必須註明作者和本文連結
支付寶領個紅包就是對我最大的讚賞了