<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>

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

          共 2050字,需瀏覽 5分鐘

           ·

          2021-01-13 14:14

          (????)??嗨,我是你穩(wěn)定更新、從不斷更的勾勾。



          上周五,我們聊了 JS 中的同步模式和異步模式。本篇,我們來嘮嘮回調(diào)函數(shù)


          異步代碼的執(zhí)行流程如下:



          通過上圖,我們會(huì)看到,在整個(gè)代碼的執(zhí)行中,JS 本身的執(zhí)行依然是單線程的,異步執(zhí)行的最終結(jié)果,依然需要回到 JS 線程上進(jìn)行處理。


          在 JS 中,異步的結(jié)果回到 JS 主線程所采用的是 “ 回調(diào)函數(shù) ” 的形式。


          所謂的回調(diào)函數(shù)就是在 JS 主線程上聲明一個(gè)函數(shù),然后將函數(shù)作為參數(shù)傳入異步調(diào)用線程,當(dāng)異步執(zhí)行結(jié)束后,調(diào)用這個(gè)函數(shù),將結(jié)果以實(shí)參的形式傳入函數(shù)的調(diào)用(也有可能不傳參,但是函數(shù)調(diào)用一定會(huì)有)。


          上篇的代碼中 setTimeout 就是一個(gè)異步方法,傳入的第一個(gè)參數(shù)就是回調(diào)函數(shù),這個(gè)函數(shù)的執(zhí)行就是消息隊(duì)列中的 “回調(diào)”。


          下面我們自己封裝一個(gè) ajax 請求,來進(jìn)一步說明回調(diào)函數(shù)與異步的關(guān)系


          Ajax 的異步請求封裝

          function myAjax(url,callback) {    var xhr = new XMLHttpRequest();    xhr.onreadystatechange = function () {        if (this.readyState == 4) {            if (this.status == 200) {                // 成功的回調(diào)                callback(null,this.responseText)            } else {                // 失敗的回調(diào)                callback(new Error(),null);            }        }    }
          xhr.open('get', url) xhr.send();}


          上面的代碼,封裝了一個(gè) myAjax 的函數(shù),用于發(fā)送異步的 ajax 請求。


          函數(shù)調(diào)用時(shí),代碼實(shí)際是按照同步模式執(zhí)行的。當(dāng)執(zhí)行到 xhr.send() 時(shí),就會(huì)開啟異步的網(wǎng)絡(luò)請求,向指定的 url 地址發(fā)送。從建立網(wǎng)絡(luò)連接到斷開網(wǎng)絡(luò)連接的整個(gè)過程是異步線程在執(zhí)行的。


          換個(gè)說法就是 myAjax 函數(shù)執(zhí)行到 xhr.send() 后,函數(shù)的調(diào)用執(zhí)行就已經(jīng)結(jié)束了。如果 myAjax 函數(shù)調(diào)用的后面有代碼,則會(huì)繼續(xù)執(zhí)行,不會(huì)等待 ajax 的請求結(jié)果。


          但是,myAjax 函數(shù)調(diào)用結(jié)束后,ajax 的網(wǎng)絡(luò)請求卻依然在進(jìn)行著。


          如果想要獲取到 ajax 網(wǎng)絡(luò)請求的結(jié)果,我們就需要在結(jié)果返回后,調(diào)用一個(gè) JS 線程的函數(shù),將結(jié)果以實(shí)參的形式傳入:

          myAjax('./d1.json',function(err,data){    console.log(data);})


          回調(diào)函數(shù)讓我們輕松處理異步的結(jié)果。但是,如果代碼是異步執(zhí)行的,而邏輯是同步的,就會(huì)出現(xiàn) “回調(diào)地獄”,舉個(gè)栗子:


          代碼 B 需要等待代碼 A 執(zhí)行結(jié)束才能執(zhí)行,而代碼 C 又需要等待代碼 B,代碼 D 又需要等待代碼 C,而代碼 A、B、C 都是異步執(zhí)行的。


          // 回調(diào)函數(shù) 回調(diào)地獄 myAjax('./d1.json',function(err,data){    console.log(data);    if(!err){        myAjax('./d2.json',function(err,data){            console.log(data);            if(!err){                myAjax('./d3.json',function(){                    console.log(data);                })            }        })    }})


          沒錯(cuò),代碼執(zhí)行是異步的。但是異步的結(jié)果,是需要有強(qiáng)前后順序的,著名的"回調(diào)地獄"就是這么誕生的。


          相對來說,代碼邏輯是固定的,但是編碼體驗(yàn)要差很多,尤其在后期維護(hù)的時(shí)候,層級嵌套太深,讓人頭皮發(fā)麻。


          如何讓我們的代碼不在地獄中受苦呢?

          下篇告訴你(? ?_?)?。


          推薦閱讀:

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

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

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

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

          是我 Web 端配不上阿里了。

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

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


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

          瀏覽 104
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  一区=区免费视频 | 高清无码视频免费版本在线观看 | 女人精品视频 | 色视频大香蕉 | 日本 波多野结衣 影片 |