1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 2809字,需瀏覽 6分鐘

         ·

        2021-01-13 22:00

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



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

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

        異步無處不在: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 的寫法只是回調(diào)函數(shù)的改進(jìn),使用then 方法以后,異步任務(wù)的兩段執(zhí)行看得更清楚了,除此以外,并無新意。


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


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


        終極異步解決方案,

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


        Async/Await 語法糖


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


        將調(diào)用異步的邏輯全部寫進(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é)果了。


        而代碼看起來的執(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ì)探究其使用的原理,無非就是兩個(gè)單詞加到前面用就好了。雖然會(huì)用,日常開發(fā)看起來也沒什么問題,但是一遇到 Bug 調(diào)試,就只能涼涼。面試的時(shí)候也總是知其然不知其所以然。


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


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


        async 面試題


        請(qǐng)寫出以下代碼的運(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')


        答案我放在最后面,你也可以自己寫出來運(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ì) *開始* 執(zhí)行 // 返回 包含 yield 內(nèi)容的對(duì)象 const yieldData = generator.next();
        console.log(yieldData) //=> {value: "yyy", done: false}// 對(duì)象中 done ,表示生成器是否已經(jīng)執(zhí)行完畢// 函數(shù)中的代碼并沒有執(zhí)行結(jié)束
        // 下一次的 next 方法調(diào)用,會(huì)從前面函數(shù)的 yeild 后的代碼開始執(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)說就是,這個(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 停一下,停下來我們就可以等待異步的結(jié)果了。


        那么如何把 Generator 寫到異步中呢?

        明天見(? ?_?)?。


        推薦閱讀:

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

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

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

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

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

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

        是我 Web 端配不上阿里了。

        不可避免的問題:React 的路由如何抽離?

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


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

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产91探花秘 入口 | 日韩精品一区二区三区波多野结衣 | 国产做a视频 | 美女撒尿 免费网站 | 囗交姿势技巧视频 | asian超清少妇肉体pics | 精品无码一区二区三区色噜噜 | 久久伊人国产 | 在线无码中文 | 一区二区乱伦视频 |