<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          異步無(wú)處不在:終極解決方案(四)

          共 2809字,需瀏覽 6分鐘

           ·

          2021-01-13 22:00

          (????)??嗨,我是你穩(wěn)定更新、持續(xù)輸出的勾勾。



          異步無(wú)處不在:同步模式和異步模式(一)

          異步無(wú)處不在:回調(diào)函數(shù)(二)

          異步無(wú)處不在:Promise 破除“回調(diào)地獄”(三)


          前三篇內(nèi)容,讓我們認(rèn)識(shí)了 JS 世界中的同步和異步模式,也清楚了回調(diào)地獄的產(chǎn)生和破解。


          回憶一下第三篇的結(jié)尾:


          雖然我們脫離了回調(diào)地獄,但是 .then 的鏈?zhǔn)秸{(diào)用依然不太友好。


          頻繁的 .then 并不符合自然的運(yùn)行邏輯,Promise 的寫(xiě)法只是回調(diào)函數(shù)的改進(jìn),使用then 方法以后,異步任務(wù)的兩段執(zhí)行看得更清楚了,除此以外,并無(wú)新意。


          Promise 的最大問(wèn)題是代碼冗余。原來(lái)的任務(wù)被 Promise 包裝了一下,不管什么操作,一眼看去都是一堆 then,原來(lái)的語(yǔ)義變得很不清楚。?


          于是,在 Promise 的基礎(chǔ)上,Async 函數(shù)出現(xiàn)了。


          終極異步解決方案,

          千呼萬(wàn)喚地在 ES2017 中發(fā)布了。


          Async/Await 語(yǔ)法糖


          Async 函數(shù)使用起來(lái),也是很簡(jiǎn)單。


          將調(diào)用異步的邏輯全部寫(xiě)進(jìn)一個(gè)函數(shù)中,函數(shù)前面使用 async 關(guān)鍵字。


          在函數(shù)中異步調(diào)用邏輯的前面使用 await ,異步調(diào)用會(huì)在 await 的地方等待結(jié)果,然后進(jìn)入下一行代碼的執(zhí)行,這就保證了代碼的后續(xù)邏輯,可以等待異步的 ajax 調(diào)用結(jié)果了。


          而代碼看起來(lái)的執(zhí)行邏輯,和同步代碼幾乎一樣。


          async function callAjax(){     var a = await myAjax('./d1.json')     console.log(a);     var b = await myAjax('./d2.json');     console.log(b)     var c = await myAjax('./d3.json');     console.log(c) }callAjax();


          注意:await 關(guān)鍵詞只能在 async 函數(shù)內(nèi)部使用。


          因?yàn)槭褂煤?jiǎn)單,很多人也不會(huì)探究其使用的原理,無(wú)非就是兩個(gè)單詞加到前面用就好了。雖然會(huì)用,日常開(kāi)發(fā)看起來(lái)也沒(méi)什么問(wèn)題,但是一遇到 Bug 調(diào)試,就只能涼涼。面試的時(shí)候也總是知其然不知其所以然。


          之前也寫(xiě)過(guò)一篇 BAT 的異步面試真題:字節(jié)百度前端面試真題:異步處理方案(內(nèi)附答案)。有興趣的小伙伴可以再次回顧下。


          咱們先來(lái)一個(gè)面試題試試,你能運(yùn)行出正確的結(jié)果嗎?


          async 面試題


          請(qǐng)寫(xiě)出以下代碼的運(yùn)行結(jié)果:

          setTimeout(function () {    console.log('setTimeout')}, 0)
          async function async1() { console.log('async1 start') await async2(); console.log('async1 end')}
          async function async2() { console.log('async2')}
          console.log('script start')
          async1();
          console.log('script end')


          答案我放在最后面,你也可以自己寫(xiě)出來(lái)運(yùn)行一下。


          想要把結(jié)果搞清楚,我們需要引入另一個(gè)內(nèi)容:Generator 生成器函數(shù)


          先看一段代碼:

          function * foo(){    console.log('test');    // 暫停執(zhí)行并向外返回值     yield 'yyy'; // 調(diào)用 next 后,返回對(duì)象值    console.log(33);}
          // 調(diào)用函數(shù) 不會(huì)立即執(zhí)行,返回 生成器對(duì)象const generator = foo();
          // 調(diào)用 next 方法,才會(huì) *開(kāi)始* 執(zhí)行 // 返回 包含 yield 內(nèi)容的對(duì)象 const yieldData = generator.next();
          console.log(yieldData) //=> {value: "yyy", done: false}// 對(duì)象中 done ,表示生成器是否已經(jīng)執(zhí)行完畢// 函數(shù)中的代碼并沒(méi)有執(zhí)行結(jié)束
          // 下一次的 next 方法調(diào)用,會(huì)從前面函數(shù)的 yeild 后的代碼開(kāi)始執(zhí)行console.log(generator.next()); //=> {value: undefined, done: true}


          你會(huì)發(fā)現(xiàn),在函數(shù)聲明的地方,函數(shù)名前面多了 * 星號(hào),函數(shù)體中的代碼有個(gè) yield ,用于函數(shù)執(zhí)行的暫停。


          簡(jiǎn)單點(diǎn)說(shuō)就是,這個(gè)函數(shù)不是個(gè)普通函數(shù),調(diào)用后不會(huì)立即執(zhí)行全部代碼,而是在執(zhí)行到 yield 的地方暫停函數(shù)的執(zhí)行,并給調(diào)用者返回一個(gè)遍歷器對(duì)象。


          yield 后面的數(shù)據(jù),就是遍歷器對(duì)象的 value 屬性值。


          如果要繼續(xù)執(zhí)行后面的代碼,需要使用遍歷器對(duì)象中的 next() 方法,代碼會(huì)從上一次暫停的地方繼續(xù)往下執(zhí)行。


          是不是 so easy!


          同時(shí),在調(diào)用 next 的時(shí)候,還可以傳遞參數(shù),函數(shù)中上一次停止的 yeild 就會(huì)接受到當(dāng)前傳入的參數(shù)。


          function * foo(){    console.log('test');    // 下次 next 調(diào)用傳參接受    const res = yield 'yyy';     console.log(res);}
          const generator = foo();
          // next 傳值 const yieldData = generator.next();console.log(yieldData)
          // 下次 next 調(diào)用傳參,可以在 yield 接受返回值generator.next('test123');


          Generator 的最大特點(diǎn)就是讓函數(shù)的運(yùn)行可以暫停


          不要小看他,有了這個(gè)暫停,我們能做的事情就太多了。在調(diào)用異步代碼時(shí),就可以先 yield 停一下,停下來(lái)我們就可以等待異步的結(jié)果了。


          那么如何把 Generator 寫(xiě)到異步中呢?

          明天見(jiàn)(? ?_?)?。


          推薦閱讀:

          異步無(wú)處不在:同步模式和異步模式(一)

          異步無(wú)處不在:回調(diào)函數(shù)(二)

          異步無(wú)處不在:Promise 破除“回調(diào)地獄”(三)

          Redux 續(xù)集 | 如何搞定其中的異步操作?

          技術(shù)人年度總結(jié) | 2020,注定不平凡

          2020 最后一篇技術(shù)文:可愛(ài)的烏咪 UmiJS

          是我 Web 端配不上阿里了。

          不可避免的問(wèn)題:React 的路由如何抽離?

          前端人因?yàn)?Vue3 的 Ref-sugar 提案打起來(lái)了!


          點(diǎn)點(diǎn)“”和“在看”,保護(hù)頭發(fā),減少bug。

          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产18禁黄网站禁片免费视频 | 成人免费电影在线观看五月天婷婷 | 久久国产一区 | 日韩无码性爱黄色电影播放 | 性无码免费一区二区三区四区 |