es6 generator 生成器學習總結 使用生成器實現異步請求, async await 的前身

 ============================生成器=========================
       生成器依賴於迭代器,生成器大量使用於react中

       什麼是生成器: 生成器是通過構造函數Generator創建的對象(只有js引擎可以使用,不提供外部調用)
        生成器既是一個迭代器,同時又是一個可迭代對象(說明生成器可以使用for of循環)

        如何創建生成器:生成器的創建,必須要使用生成器函數(Generator Function)

        如何創建一個生成器函數: 如下:
          // 在函數名稱前面加上一個*號,標記着該函數是一個生成器函數, 和加async標記異步是一樣的,但是不能兩個同時加
            function *methondsName(){
                // 是給迭代器每一次迭代運行的數據
                // 每一次調用生成器的next()方法,將導致生成器函數運行到下一個yield關鍵字位置
            }

            或者:
             function* methondsName(){
                 // 是給迭代器每一次迭代運行的數據
                // 每一次調用生成器的next()方法,將導致生成器函數運行到下一個yield關鍵字位置
            }

            通過生成器函數獲取生成器
          const generator = methondsName();

        yeild: 是一個關鍵字, 該關鍵字只能在生成器函數內部使用,表達“產生”一個迭代數據

         使用方法:
          function* test() {
            console.log("第一次運行");
            yield 1;
            console.log("第二次運行");
            yield 2;
            console.log("第三次運行")
        }   

        // 迭代運行數組
        function* createIterator(arr) {
            for (const item of arr) {
                yield item;
            }
        }

        // 調用生成一個生成器
        const arr = [1,2,3,4,5,6]
        const ci = createIterator(arr);
        ci.next() // 每一次調用打印數組裏面迭代的值,直到迭代完成

       生成器注意:
        1. 生成器可以存在有返回值,在迭代結束的時候return的值會賦值給value(迭代器返回對象的value)的值 
        2. 調用生成器的next() 可以傳遞參數,傳遞參數交給yield的表達式的返回值

            例如:
            function* test() {
                let info = yield 1;
                info = yield 2 + info
            }

            const generator = test();
            generator.next() // value: 1, done: false
            generator.next(5) // value: 6, done: false
            generator.next(5) // value: undefined, done: true
        3. 生成器第一次調用next()方法時候,傳遞的參數沒有任何意義
        4. 在生成器內部可以調用其他生成器的函數,調用方式如下:
           
                function* test() {
                    yield 1;
                    yield 2;
                }

                function* test2() {
                    yield* test(); // 這樣調用其他生成器的代碼
                    yield 3;
                    yield 4;
                }

        5.  生成器的其他API   
           return(): 調用該方法可以提前結束生成器
           throw(): 調用該方法,可以在生成器裏面拋出一個錯誤


           /**
            * 使用生成器來模擬 async await 處理異步 
            * @description:  生成器,來執行異步代碼
            * @param : generatorFunc 一個生成器對象
            * @return: 
            */
            function run(generatorFunc) {
                // 執行生成器,創建一個生成器
                const generator = generatorFunc();
                // 先執行生成器的next()方法, 啓動生成器
                const result = generator.next();
                // 後面判斷是否要繼續執行next() 方法
                handleResult(result);

                /**
                * @description: 執行後續生成器的結果
                * @param :  result {*} 生成器對象
                * @return: 
                */
                function handleResult(result) {
                    // 判斷後續處理是福繼續,如果爲true, 則表示迭代失敗,爲false, 繼續迭代
                    if (result.done) {
                        return;
                    }
                    // 然後繼續迭代,存在兩種數據情況
                    // 1. 迭代的數據是一個promise 異步代碼
                    // 2. 迭代的數據是一個其他數據, 也就是同步代碼

                    // 此處判斷迭代結果 的值是否有一個then函數
                    if (typeof result.value.then === "function") {
                        // 1. 迭代的數據是一個promise 異步代碼
                        result.value.then(data => {
                            const nextResult = generator.next(data);
                            handleResult(nextResult);
                        }, err => {
                            // promise 失敗, 生成器內部拋出一個錯誤
                            generator.throw(err);
                            const nextResult = generator.next(data);
                            handleResult(nextResult);

                        })
                    } else {
                        // 2. 迭代的數據是一個其他數據, 也就是同步代碼

                        // 把上一次迭代的結果傳給下一次迭代
                        const nextResult = generator.next(result.value);
                        handleResult(nextResult);
                    }
                }
            }

            function* task() {
                const d = yield 1;
                console.log(d);
                const dd = yield 1;
                console.log(dd);

                const resp = yield fetch("xxxx.xxx.xxxx");
                console.log(resp)
                const res = yield resp.json();
                console.log(res)
            }
            
            run(task);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章