javascript
javascript生成器
next()方法
如果給next方法傳參數(shù), 那么這個(gè)參數(shù)將會(huì)作為上一次yield語句的返回值 ,這個(gè)特性在異步處理中是非常重要的, 因?yàn)樵趫?zhí)行異步代碼以后, 有時(shí)候需要上一個(gè)異步的結(jié)果, 作為下次異步的參數(shù), 如此循環(huán)::
Generator函數(shù)返回的Iterator執(zhí)行next()方法以后, 返回值的結(jié)構(gòu)為:
{value : "value", //value為返回的值done : false //done的值為一個(gè)布爾值, 如果Interator未遍歷完畢, 他會(huì)返回false, 否則返回true; }如果給next方法傳參數(shù), 那么這個(gè)參數(shù)將會(huì)作為上一次yield語句的返回值 ,這個(gè)特性在異步處理中是非常重要的, 因?yàn)樵趫?zhí)行異步代碼以后, 有時(shí)候需要上一個(gè)異步的結(jié)果, 作為下次異步的參數(shù), 如此循環(huán)
throw方法
如果執(zhí)行Generator生成器的throw()方法, 如果在Iterator執(zhí)行到的yield語句寫在try{}語句塊中, 那么這個(gè)錯(cuò)誤會(huì)被內(nèi)部的try{}catch(){}捕獲 ,如果Interator執(zhí)行到的yield沒有寫在try{}語句塊中, 那么這個(gè)錯(cuò)誤會(huì)被外部的try{}catch(){}語句塊捕獲;
<script> var g = function* () {try {yield;} catch (e) {console.log('內(nèi)部捕獲0', e);} };var i = g(); i.next(); //讓代碼執(zhí)行到y(tǒng)ield處; try {i.throw('a'); } catch (e) {console.log('外部捕獲', e); } </script> function *ylj(){try{var a1 = yield 1;var a2 = yield a1+1;var a3 = yield a2 + 2;console.log('over');}catch(err){console.log(err);}var a4 = yield 7758console.log('out'); }var it = ylj(); console.log(it.next()); console.log(it.throw('error')) console.log(it.next())/控制臺(tái)顯示結(jié)果
{value: 1, done: false}
error
{value: 7758, done: false}
out
{value: undefined, done: true}
?注意:it.throw會(huì)向生成器拋出一個(gè)錯(cuò)誤,如果生成器內(nèi)部有try...catch,立刻跳出try{},執(zhí)行catch內(nèi)的函數(shù),就能夠捕獲錯(cuò)誤,如果try..catch外還有yield,it.throw還會(huì)自動(dòng)執(zhí)行try..catch外的第一個(gè)yield,并返回一個(gè)對象,例如"{value: 7758, done: false}"。
return()方法
function* gen() {yield 0;yield 1;yield 2;yield 3; }; let g = gen(); console.log(g.return("heheda")); //輸出:{ value: 'heheda', done: true }?
如果執(zhí)行Iterator的return()方法, 那么這個(gè)迭代器的返回會(huì)被強(qiáng)制設(shè)置為迭代完畢, 執(zhí)行return()方法的參數(shù)就是這個(gè)Iterator的返回值,此時(shí)done的狀態(tài)也為true:
1. 迭代消息傳遞
function *foo(x) { var y = x * (yield); return y; } var it = foo( 6 ); // 啟動(dòng)foo(..) it.next(); var res = it.next( 7 ); res.value; // 42?首先,傳入 6 作為參數(shù) x 。然后調(diào)用 it.next() ,這會(huì)啟動(dòng) *foo(..) 。在 *foo(..) 內(nèi)部,開始執(zhí)行語句 var y = x .. ,但隨后就遇到了一個(gè) yield 表達(dá)式。它就會(huì)在這一點(diǎn)上暫停 *foo(..) (在賦值語句中間!),并在本質(zhì)上要求調(diào)用代碼為 yield表達(dá)式提供一個(gè)結(jié)果值。接下來,調(diào)用 it.next( 7 ) ,這一句把值 7 傳回作為被暫停的yield 表達(dá)式的結(jié)果。
一般來說,需要的 next(..) 調(diào)用要比 yield 語句多一個(gè),前面的代碼片段有一個(gè) yield 和兩個(gè) next(..) 調(diào)用
因?yàn)榈谝粋€(gè) next(..) 總是啟動(dòng)一個(gè)生成器,并運(yùn)行到第一個(gè) yield 處。不過,是第二個(gè)next(..) 調(diào)用完成第一個(gè)被暫停的 yield 表達(dá)式,第三個(gè) next(..) 調(diào)用完成第二個(gè) yield ,以此類推
最后一個(gè)next(),即如果done屬性為true,則返回return 的值,如果沒有就返回undefined。
生成器的起始處我們調(diào)用第一個(gè) next() 時(shí),還沒有暫停的 yield 來接受這樣一個(gè)值。規(guī)范和所有兼容瀏覽器都會(huì)默默丟棄傳遞給第一個(gè) next() 的任何東西。傳值過去仍然不是一個(gè)好思路,因?yàn)槟銊?chuàng)建了沉默的無效代碼,這會(huì)讓人迷惑。因此,啟動(dòng)生成器時(shí)一定要用不帶參數(shù)的 next()。
二、
for..of 循環(huán)在每次迭代中自動(dòng)調(diào)用 next() ,它不會(huì)向 next() 傳入任何值,并且會(huì)在接收到 done:true 之后自動(dòng)停止。這對于在一組數(shù)據(jù)上循環(huán)很方便。
除了構(gòu)造自己的迭代器,許多 JavaScript 的內(nèi)建數(shù)據(jù)結(jié)構(gòu)(從 ES6 開始),比如 array ,也有默認(rèn)的迭代器:
var a = [1,3,5,7,9]; for (var v of a) { console.log( v ); } // 1 3 5 7 9for..of 循環(huán)向 a 請求它的迭代器,并自動(dòng)使用這個(gè)迭代器迭代遍歷 a 的值。
三、
function foo(x, y) {ajax("http://some.url.1/?x=" + x + "&y=" + y,function(err, data) {if (err) {// 向*main()拋出一個(gè)錯(cuò)誤it.throw(err);} else {// 用收到的data恢復(fù)*main()it.next(data);}}); }function* main() {try {var text = yield foo(11, 31);console.log(text);} catch (err) {console.error(err);} } var it = main();?
var text = yield foo( 11, 31 ); console.log( text );?我們調(diào)用了一個(gè)普通函數(shù) ajax(..) ,而且顯然能夠從 Ajax 調(diào)用中得到 text ,即使它是異步的。
但是,下面這段代碼不能工作!你能指出其中的區(qū)別嗎?區(qū)別就在于生成器中使用的 yield 。
var data = foo( "..url 1.." ); console.log( data );?正是這一點(diǎn)使得我們看似阻塞同步的代碼,實(shí)際上并不會(huì)阻塞整個(gè)程序,它只是暫停或阻塞了生成器本身的代碼。
這意味著什么。我們在生成器內(nèi)部有了看似完全同步的代碼(除了 yield 關(guān)鍵字本身),但隱藏在背后的是,除開生成器,在foo函數(shù)或大環(huán)境內(nèi)的運(yùn)行可以完全異步。
同步處理錯(cuò)誤:
try { var text = yield foo( 11, 31 ); console.log( text ); } catch (err) { console.error( err ); }??yield讓賦值語句暫停來等待 foo(..) 完成,使得響應(yīng)完成后可以被賦給 text 。 yield 暫停也使得生成器能夠捕獲錯(cuò)誤。通過這段前面列出的代碼把錯(cuò)誤拋出到生成器中:
?前端交流群請加群:277942610
轉(zhuǎn)載于:https://www.cnblogs.com/liumingwang/p/10216073.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的javascript生成器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 京东云金山云合并确有其事,或拉开云计算兼
- 下一篇: 面试题解(3):SQL