生成器

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            // yield關鍵字,可以讓代碼在其出現的地方暫停執行,它只能在生成器函數內部使用。
            // 第一次調用,函數里面 yield之前的代碼不會執行,需要調next方法,yield之前的代碼才會執行
            // 但是 yield之后的代碼不會執行(yield語句會執行,yield 右邊的會執行,yield x++,下面的不會而已),需要繼續next方法才會執行yield之后的代碼
            // next方法 返回一個對象 ,value屬性,value屬性的值是當前yield語句的結果
            // done:true/false,是否迭代結束,true已迭代結束,繼續調next方法,value則返回undefined
            // false則表示未迭代結束,可以繼續調用next()
            // next方法可以接收參數,第一個next傳遞參數并不會被接收,只有從第二個next開始傳遞的參數才會被接收
            // 如果一個生成器函數中使用return,我們需要得到return的值,
            // 這時候需要使用next方法返回的對象的value屬性得到返回的值。
            // 生成器函數
            // 生成器函數的語法比較簡單在普通函數聲明的時候在函數名前面添加一個*即可,如下所示:
            
            // 場景:判斷是否需要繼續發請求,放done為true的時候停止
            // function *gen(){}


            // 當函數被調用時會返回一個返回值,但是生成器函數與普通函數的返回值有些區別。
            // 普通函數如果沒有使用return返回時,接收到的是undefined,
            // 而生成器函數不管有沒有return都返回一個對象,這個對象被稱為迭代器,
            // 我們可以通過這個對象控制迭代器的執行。 通常, 使用迭代器的next方法, 讓其繼續執行。

            // let x = 0;

            // function* gen() {
            //  console.log(x);
            //  yield x++;
            // }
            // let itr = gen(); //函數的里代碼console.log(x);不會執行
            // console.log(itr); //返回一個gen函數名對象
            // itr.next()//函數的里代碼console.log(x)執行了
            // console.log(x);// yield x++; 也執行了 1
            //根據上面的結果我們可以知道,生成器函數在被調用時并不會開始執行代碼,但是得到了一個對象,
            //我們讓它繼續執行函數內的代碼,需要調用next方法。

            // 看看next方法輸出什么
            let x = 0;

            function* gen() {
                console.log(x);
                yield x++;
                console.log("ssssss",x);
                return x;
            }
            let itr = gen();
            let res = itr.next();
            console.log(res); //{value: 1, done: true}
            //next方法也會返回一個對象,這個對象包含一個value屬性,value屬性的值是當前yield語句的結果。
            //則是yield后面 x++ 的結果;
            //還有one屬性的值表示迭代器的完成狀態,為true表明完成迭代,為false,表明沒有完成迭代。
            // console.log(res.value);
            res = itr.next();
            console.log(res.value, res);
            res = itr.next();
            console.log(res);
            //如果一個生成器函數中使用return,我們需要得到return的值,
            //這時候需要使用next方法返回的對象的value屬性得到返回的值。

            // next方法也可以接收一個值

            // let x = 0;
            // function *gen(){
            //  console.log(yield);
            //   x++;
            //  return x;
            // }
            // let itr = gen();
            // let res = itr.next(6);
            // console.log(res);
            // res = itr.next(7);
            // console.log(res);

            // 根據結果我們可以知道, 第一個next傳遞參數并不會被接收, 
            // 規范和所有兼容瀏覽器都會默默丟棄傳遞給第一個next() 的任何東西。 
            // 傳值過去仍然不是一個好思路, 因為你創建了沉默的無效代碼, 這會讓人迷惑。 
            // 因此, 啟動生成器時一定要用不帶參數的next()。

            // 只有從第二個next開始傳遞的參數才會被接收, 由此, 我們可以總結, 
            // next傳遞的值被上一個yield接收, next與field相差一個間隔。

            // 那么為什么會產生這個差距呢?

            // 因為第一個next(…) 總是啟動一個生成器, 并運行到第一個yield處。 
            // 不過, 是第二個next(…) 調用完成第一個被暫停的yield表達式, 第三個next(…) 調用完成第二個yield, 以此類推。

            // 以上就是生成器函數的基本使用, 那么生成器函數到底有什么用或者說能夠應用在什么場景呢?

            // 生成器函數可以應用在異步任務中, 
            // 當一個異步任務沒有返回值時我們可以讓程序在此處暫停當有返回值時在調用next繼續執行。
            
            // function run(gen) {
            //   var args = [].slice.call(arguments, 1), it;
            
            //   // 在當前上下文中初始化生成器
            //   it = gen.apply(this, args);
            
            //   // 返回一個promise用于生成器完成
            //   return Promise.resolve()
            //     .then(function handleNext(value) {
            //       // 對下一個yield出的值運行
            //       var next = it.next(value);
            
            //       return (function handleResult(next) {
            //         // 生成器運行完畢了嗎?
            //         if (next.done) {
            //           return next.value;
            //         }
            //         // 否則繼續運行
            //         else {
            //           return Promise.resolve(next.value)
            //             .then(
            //               // 成功就恢復異步循環,把決議的值發回生成器
            //               handleNext,
            //               // 如果value是被拒絕的promise,
            //               // 就把錯誤傳回生成器進行出錯處理
            //               function handleErr(err) {
            //                 return Promise.resolve(it.throw(err)).then(handleResult);
            //               }
            //             );
            //         }
            //       })(next);
            //     });
            // }

        </script>
    </body>
</html>
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容