您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)es5中yield和es6的aysnc/await有什么用,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
最近的業(yè)余時(shí)間在看 js 相關(guān)的書, 也在極客時(shí)間上買了前端相關(guān)的專欄, 對(duì)于一個(gè)非 jser 的人來說, 時(shí)時(shí)會(huì)有一種感覺: js 社區(qū)是真的激進(jìn)和浮燥, 這幫規(guī)則的制定者似乎從來也不知道克制為何物. 有很多時(shí)候固有的東西是可以處理好的, 但是偏偏喜歡人為制造一些概念和語法糖, 人為的建起一座又一座的高山, 似乎你沒跨過就是個(gè) "菜雞"
請(qǐng)?jiān)徫业膼憾? 看《js 語言精粹》的時(shí)候, 這種感覺非常的強(qiáng)烈. 作者是業(yè)內(nèi)的大牛, 還制定了 json, 但是每一章還在最開頭引一句莎翁的話, "似乎無關(guān)緊要又暗藏哲理". 書中很多內(nèi)容要表達(dá)的意思總有一種: 明明可以將話說成 10 分讓一個(gè)普通人都能看得明白的, 卻偏不, 只說 6 分, 剩下的自己去悟, 有很多規(guī)則性的東西并非是靠悟, 而是靠幾句話說清楚其本質(zhì)就豁然開朗的.
換成以前, 會(huì)覺得這人是一座好大的高山要進(jìn)行膜拜, 這幾年雖然自己技術(shù)依然不那么好, 但是還是喜歡去思考一些內(nèi)在的東西, 更在努力一點(diǎn)一點(diǎn)把心里的權(quán)威崇拜給去掉, 再看到這些的時(shí)候, "..." 這幾個(gè)標(biāo)點(diǎn)符號(hào)很容易印在腦子里. 感覺這不只是一兩個(gè)人這樣, 極有可能是整個(gè) js 圈子都是這樣
說回標(biāo)題上來, 除了看書, 看專欄, 找資料, 很久都還是沒有把 generator 和 async/await 給理解透, 于是自己試著整個(gè)梳理了一下運(yùn)行的流程
我先試著在 yield 后面不跟任何的東西, 可以直接復(fù)制到控制臺(tái)輸出
function *f0(param) { console.log('n: ' + param); yield; console.log('i'); let l = yield; console.log('l: ' + l); } let v0 = f0('p'); console.log(v0.next(1)); // 輸出 n: p 和 {value: undefined, done: false} console.log('----'); console.log(v0.next(2)); // 輸出 i 和 {value: undefined, done: false} console.log('----'); console.log(v0.next(3)); // 輸出 l: 3 和 {value: undefined, done: true} console.log('----'); console.log(v0.next(4)); // 輸出 {value: undefined, done: true} console.log('----'); console.log(v0.next(5)); // 輸出 {value: undefined, done: true}
在上面的基礎(chǔ)上給方法 return 值
function *f1() { console.log('n'); yield; console.log('i'); let l = yield; console.log('l: ' + l); return '?'; } let v1 = f1(); console.log(v1.next(1)); // 輸出 n 和 {value: undefined, done: false} console.log('----'); console.log(v1.next(11)); // 輸出 i 和 {value: undefined, done: false} console.log('----'); console.log(v1.next(111)); // 輸出 l: 111 和 {value: '?', done: true} console.log('----'); console.log(v1.next(1111)); // 輸出 {value: undefined, done: true} console.log('----'); console.log(v1.next(11111)); // 輸出 {value: undefined, done: true}
然后我試著在 yield 的后面加上內(nèi)容
function *f2(param) { console.log('0: ' + param); let f = yield 1; console.log('1: ' + f); let s = yield f + 2; console.log('2: ' + s); let t = yield (s + 3); console.log('3: ' + t); let fo = (yield s) + 4; console.log('4: ' + fo); } let v2 = f2('p'); console.log(v2.next('N')); // 輸出 0: p 和 {value: 1, done: false} console.log('----'); console.log(v2.next('I')); // 輸出 1: I 和 {value: "I2", done: false} console.log('----'); console.log(v2.next('L')); // 輸出 2: L 和 {value: "L3", done: false} console.log('----'); console.log(v2.next('S')); // 輸出 3: S 和 {value: "L", done: false} console.log('----'); console.log(v2.next('H')); // 輸出 4: H4 和 {value: undefined, done: true} console.log('----'); console.log(v2.next('I')); // 輸出 {value: undefined, done: true} console.log('----'); console.log(v2.next('T')); // 輸出 {value: undefined, done: true}
最后, 在上面的基礎(chǔ)上給方法 return 值
function *f3() { console.log('0'); let y1 = yield 1; console.log('1: ' + y1); let y2 = yield y1 + 2; console.log('2: ' + y2); let y3 = yield (y2 + 3); console.log('3: ' + y3); let y4 = (yield y3) + 4; console.log('4: ' + y4); return '??'; } let v3 = f3(); console.log(v3.next('N')); // 輸出 0 和 {value: 1, done: false} console.log('----'); console.log(v3.next('I')); // 輸出 1: I 和 {value: "I2", done: false} console.log('----'); console.log(v3.next('L')); // 輸出 2: L 和 {value: "L3", done: false} console.log('----'); console.log(v3.next('S')); // 輸出 3: S 和 {value: "S", done: false} console.log('----'); console.log(v3.next('H')); // 輸出 4: H4 和 {value: "??", done: true} console.log('----'); console.log(v3.next('I')); // 輸出 {value: undefined, done: true} console.log('----'); console.log(v3.next('T')); // 輸出 {value: undefined, done: true}
大致上就清楚 yield 的運(yùn)行邏輯了, 以上面的 f3 為例, 對(duì)照上面的輸出來看, 它其實(shí)是將一個(gè)方法分成了這樣幾段來執(zhí)行
// 下面 五行一起的豎線(|) 用一個(gè)大括號(hào)表示出來會(huì)更直觀一點(diǎn) function *f3() { // 調(diào)用第 1 次 next('N') 時(shí)運(yùn)行的代碼 console.log('0'); let y1 = yield 1; return 1; // | 封裝成 {value: 1, done: false} 返回 // | // | 這兩行等同于 let y1 = yield 1; // 調(diào)用第 2 次 next('I') 時(shí)運(yùn)行的代碼 // | let y1 = 'I'; // | console.log('1: ' + y1); return y1 + 2; // | 封裝成 {value: "I2", done: false} 返回 // | // | 這兩行等同于 let y2 = yield y1 + 2; // 調(diào)用第 3 次 next('L') 時(shí)運(yùn)行的代碼 // | let y2 = 'L'; // | console.log('2: ' + y2); return y2 + 3; // | 封裝成 {value: "L3", done: false} 返回 // | // | 這兩行等同于 let y3 = yield (y2 + 3); // 調(diào)用第 4 次 next('S') 時(shí)運(yùn)行的代碼 // | let y3 = 'S'; // | console.log('3: ' + y3); return y3; // | 封裝成 {value: "S", done: false} 返回 // | // | 這兩行等同于 let y4 = (yield y3) + 4; // 調(diào)用第 5 次 next('H') 時(shí)運(yùn)行的代碼 // | let y4 = 'H' // | console.log('4: ' + y4); return '??'; // 封裝成 {value: "??", done: true} 返回 }
再回頭想一想就知道了, 第一次運(yùn)行 next('N') 的時(shí)候, 傳進(jìn)去的 N 是會(huì)被忽略的, 因?yàn)榈谝淮?next() 傳的值沒有 yield 前面來接收. 再去看書也好, 看查到的文章也好, 第一次 next() 都是沒有傳過參數(shù)
感覺 yield 就是為了迭代而生的, 迭代完全可以就用 for 啊, 但是卻繞成這樣, 也不知道這是為哪般! 就這還能新弄一個(gè) for of 玩出花來, 因?yàn)槊繄?zhí)行 next() 才會(huì)執(zhí)行那一段段, 還美其名曰 "咱們終于可以異步了"
再是 es7 開始有的這倆關(guān)鍵字, 看了一個(gè)大廠的面試題, 自己為了加深對(duì)這兩個(gè)關(guān)鍵字的理解改了一下成下面這樣
async function async1() { console.log('A'); console.log(await async2()); return 'B'; } async function async2() { console.log('C'); return 'D'; } console.log('E'); setTimeout(function() { console.log('F'); }, 0); async1().then(function(r) { console.log(r); }); new Promise(function(resolve, reject) { console.log('G'); resolve(); }).then(function() { console.log('H'); }); console.log('I');
在 chrome 73.0.3683.75 底下的輸出是:
// 這個(gè) undefined 的意思應(yīng)該主要是用來分隔宏任務(wù)的, 也就是前面的主線和任務(wù)隊(duì)列是在一起的 E A C G I D H B undefined F
在 firefox 60.5.1 底下的輸出
// 這個(gè) undefined 的意思應(yīng)該只是用來分隔主線的, 任務(wù)隊(duì)列和宏任務(wù)在一起了 E A C G I undefined H D B F
在 opera 58.0.3135.107 底下的輸出是:
// 這個(gè) undefined 應(yīng)該跟 chrome 里面是一樣的 E A C G I H D B undefined F
明顯 D H B 是比較合理的. 在 firefox 和 opera 的實(shí)現(xiàn)中明顯是有問題的, 想像得到, 低版本一點(diǎn)的 chrome 也可能是后面的結(jié)果
還有像 var let const 這種一個(gè)簡(jiǎn)單的賦值都能玩出這么多花樣(當(dāng)然, 這可以說是歷史遺留問題導(dǎo)致的)
老實(shí)說, 我覺得這更多是為了: "別的語言有, 咱們這么前衛(wèi)的語言當(dāng)然應(yīng)該要有!"
...
就這么樣一門語言, 居然可以流行成現(xiàn)在這樣, 只能說這個(gè)世界是真奇妙
關(guān)于es5中yield和es6的aysnc/await有什么用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。