<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #### 打破函數的完整運行 ``` var x = 1; function *foo() { x++; yield; console.log("x:" + x); } function bar() { x++; } //foo()并不會立即執行函數,而僅僅是構造了一個生成器 var it = foo(); //只有.next()才會真正執行函數,直到遇見yield暫停 it.next(); x; //2 bar(); it.next(); //x:3 ``` next()會返回一個對象 ``` function *foo() { var x = 0; yield; x++; yield; return x; } var it = foo(); it.next(); //{value: undefined, done: false} it.next(); //{value: undefined, done: false} it.next(); //{value: 1, done: true} ``` next也可以接收參數,作為yield的返回值 ``` //注意yield的關鍵字,加上括號以區分變量 function *foo(x) { var y = x * (yield); return y; } var it = foo(6); it.next(); var res = it.next(7); res.value; //42 ``` next可以將消息傳遞給yield,同樣的,yield也可以給next傳遞消息 ``` function *foo() { var y = x * (yield "hello"); return y; } var it = foo(6); var res = it.next(); res.value; //hello it.next(7).value; //42 ``` it.return(arg)終止生成器(done:true),arg將作為最終的value值。 #### 異步請求 ``` function foo(x, y) { ajax(url, data, (err, data) => if(err) it.throw(err); else it.next(data)); } function *main() { var text = yield foo(2, 3); console.log(text); } var it = main(); it.next(); //qinchuan(from server) ``` 想想上述代碼的邏輯:it.next()啟動這個生成器,走到yield foo(2, 3)時暫停,執行foo函數并將函數返回值返回給上一個it.next().value(undefined),相當于yield undefined。而yield在等待下一個next,請求回來后,調用it.next(data),生成器繼續執行,data作為yield的返回值返回給text。 如何錯誤處理? ``` function foo(x, y) { ajax(url, data, (err, data) => if(err) it.throw(err); else it.next(data)); } function *main() { try { var text = yield foo(2, 3); console.log(text); } catch(err) { //it.throw(err)會在這里捕捉到 console.error(err); } } //外部捕獲也可以 //清空上述代碼 function *main() { var x = yield "hello world"; yield x.toLowerCase(); } var it = main(); it.next(); //value為hello world try { it.next(42); //x為42 執行x.toLowerCase()報錯 } catch(err) { console.log(err); //TypeError } ``` #### 生成器+Promise ``` function foo(x, y) { return new Promise((resolve, reject) => { ajax(url + x + y, data => resolve(data), err => reject(err)); }) } function *main() { try { var text = yield foo(2, 3); console.log(text); } catch(err) { console.log(err) } } var it = main(); var ajaxBK = it.next().value; ajaxBK.then(data => it.next(data), err => it.throw(err)); ``` 并發請求 ``` function *foo() { //yield -> res var results = yield Promise.all([request1(), request2()]); var r1 = results[0]; var r2 = results[1]; //yield -> res3 var r3 = yield request3(); console.log(r3); } var it = foo(); var rp12 = it.next().value; rp12.then(res => { var rp3 = it.next(res).value; rp3.then(res3 => it.next(res3);); }); ``` #### 生成器委托 ``` function *foo() { console.log('foo start') yield 3; yield 4; } function *bar() { yield 1; yield 2; yield *foo(); yield 5; console.log('finish') } var it = bar(); it.next().value; //1 it.next().value; //2 it.next().value; //foo start //3 it.next().value; //4 it.next().value; //5 it.next(); //finish ``` 當走到yield *foo()時,自動執行foo().next()啟動foo,此時的it變成了foo,foo執行完畢后it又變回bar 看得懂下面的例子,你就懂委托了 ``` function *foo() { console.log("inside *foo()", yield "B"); console.log("inside *foo()", yield "C"); return "D"; } function *bar() { console.log("inside *bar()", yield "A"); console.log("inside *bar()", yield *foo()); console.log("inside *bar()", yield "E"); return "F"; } var it = bar(); console.log("outside:", it.next().value); //outside: A console.log("outside:", it.next(1).value); //inside *bar() 1 //outside: B console.log("outside:", it.next(2).value); //inside *foo() 2 //outside: C console.log("outside:", it.next(3).value); //inside *foo() 3 //inside *bar() D //outside:E console.log("outside:", it.next(4).value); //inside *bar() 4 //outside: F ``` yield委托的不一定必須是另一個生成器,也可以是一個iterable ``` function *bar() { console.log("inside *bar()", yield "A"); console.log("inside *bar()", yield *["B", "C", "D"]); console.log("inside *bar()", yield "E"); return "F"; } var it = bar(); console.log("outside:", it.next().value); //outside: A console.log("outside:", it.next(1).value); //inside *bar() 1 //outside: B console.log("outside:", it.next(2).value); //outside: C console.log("outside:", it.next(3).value); //outside: D console.log("outside:", it.next(4).value); //inside *bar() undefined //outside: E iterable返回的是undefined console.log("outside:", it.next(5).value); //inside *bar() 5 //outside: F ``` 異常也會被委托,但是,如果內層生成器的異常沒有在外層捕獲處理的話,那么外層生成器將會置為done ``` function *foo() { try { yield "B"; } catch(err) { console.log("error caught inside *foo()", err); } yield "C"; throw "D"; } function *bar() { yield "A"; try { yield *foo(); } catch(err) { console.log("error caught inside *bar()", err); } yield "E"; yield *baz(); yield "G"; } function *baz() { throw "F"; } var it = bar(); console.log("outside:", it.next().value); //outside: A console.log("outside:", it.next(1).value); //outside: B console.log("outside:", it.throw(2).value); //error caught inside *foo() 2 //outside: C console.log("outside:", it.next(3).value); //error caught inside *bar() D //outside: E try { console.log("outside:", it.next(4).value); } catch(err) { console.log("error caught outside:", err); //error caught outside: F } //baz中出現異常,而外部的bar并沒有將其捕獲,導致異常繼續向上傳遞到最外層被捕獲,同時出現異常的baz和外部函數bar均進入到了done階段,G永遠不會走到。 ``` #### 生成器并發 ``` //request是promise類型的ajax var res = []; function *reqData(url) { var data = yield request(url); yield; res.push(data); } var it1 = reqData(url1); var it2 = reqData(url2); var p1 = it1.next().value; var p2 = it2.next().value; p1.then(res1 => it1.next(res1)); p2.then(res2 => it2.next(res2)); Promise.all([p1, p2]).then(() => {it1.next(); it2.next();}) ``` #### 形實轉換工具(thunk) thunk:一個用于調用另一個函數的函數,自身沒有參數 ``` function foo(x, y) { return x + y; } function fooThunk() { return foo(3, 4); } fooThunk(); //7 //異步thunk,可以有回調 function foo(x, y, cb) { setTimeout(() => cb(x + y), 1000); } function fooThunk(cb) { foo(3, 4, cb); } fooThunk(sum => console.log(sum);); //7 ``` 封裝 ``` function thunkify(fn) { var args = [].slice.call(arguments, 1); // -> [3, 4], 如果沒有那個1的話將會是[fn, 3, 4] return function(cb) { args.push(cb); // -> [3, 4, (sum) => console.log(sum)] return fn.apply(null, args); } } var fooThunk = thunkify(foo, 3, 4); fooThunk(sum => console.log(sum)); //7 function thunkify(fn) { return function() { var args = [].slice.call(arguments); return function(cb) { args.push(cb); return fn.apply(null, args); } } } var fooThunkory = thunkify(foo); var fooThunk1 = fooThunkory(3, 4); var fooThunk2 = fooThunkory(5, 6); fooThunk1(sum => console.log(sum)); //7 fooThunk2(sum => console.log(sum)); //11 ``` #### 手動實現生成器 p280頁,掌握其原理
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看