最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS異步的執(zhí)行原理和回調(diào)詳解

 更新時(shí)間:2021年03月08日 11:24:24   作者:Zxinxxxx  
這篇文章主要給大家介紹了關(guān)于JS異步的執(zhí)行原理和回調(diào)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、JS異步的執(zhí)行原理

  我們知道JavaScript是單線(xiàn)程的,而瀏覽器是多線(xiàn)程的。單線(xiàn)程執(zhí)行任務(wù)需要一個(gè)個(gè)排隊(duì)進(jìn)行,假如一個(gè)任務(wù)需要很長(zhǎng)時(shí)間執(zhí)行(像ajax需要較長(zhǎng)時(shí)間),會(huì)直接導(dǎo)致無(wú)響應(yīng),后面的任務(wù)一直在等待執(zhí)行。這時(shí)候就需要用到異步。

  想了解異步,首先我們要知道瀏覽器有最基本的三個(gè)常駐線(xiàn)程: JS引擎線(xiàn)程,事件觸發(fā)線(xiàn)程,GUI渲染線(xiàn)程。

  其中JS引擎線(xiàn)程和事件觸發(fā)線(xiàn)程共同構(gòu)成了一種事件循環(huán)機(jī)制,而GUI渲染線(xiàn)程與JS引擎是互斥的,當(dāng)JS引擎執(zhí)行時(shí)GUI線(xiàn)程會(huì)被掛起,GUI更新保存在一個(gè)隊(duì)列中,當(dāng)JS引擎空閑時(shí),立即被執(zhí)行。

  我們從它的事件循環(huán)機(jī)制解析:

  JS引擎線(xiàn)程中分為同步和異步任務(wù):

    1.同步任務(wù)全部通過(guò)主線(xiàn)程執(zhí)行,形成執(zhí)行棧。

    2.當(dāng)有異步任務(wù)時(shí)交給異步進(jìn)程(WebAPIs):包含事件觸發(fā)線(xiàn)程或者定時(shí)器線(xiàn)程等處理,形成任務(wù)隊(duì)列。

    3.當(dāng)執(zhí)行棧中的任務(wù)全部處理完成,主線(xiàn)程為空閑的時(shí)候,會(huì)從任務(wù)隊(duì)列中提取任務(wù)到執(zhí)行棧中執(zhí)行。

  通俗來(lái)說(shuō),JavaScript除了主線(xiàn)程之外還存在一個(gè)任務(wù)隊(duì)列,任務(wù)隊(duì)列存放需要異步執(zhí)行的內(nèi)容,執(zhí)行完主線(xiàn)程后,就會(huì)不斷循環(huán)掃描執(zhí)行任務(wù)隊(duì)列的任務(wù),直至隊(duì)列清空。

畫(huà)解:

  如圖小明因?yàn)閷W(xué)習(xí)耗時(shí)長(zhǎng)會(huì),如果沒(méi)做完就會(huì)一直無(wú)法玩DNF游戲了,就把學(xué)習(xí)放到了異步任務(wù)隊(duì)列中,等玩完游戲(主線(xiàn)程)再學(xué)習(xí)(任務(wù)隊(duì)列)。期間母親添加學(xué)習(xí)事件(DOM事件),小明每完成一個(gè)學(xué)習(xí)任務(wù)就看看還有啥任務(wù)(循環(huán)掃描),直至最后做完.

  下面再看一個(gè)例子(瀏覽器刷新不斷點(diǎn)擊按鈕):

  let myData = null
  //ajax請(qǐng)求
  function ajax() {
  //騰訊新冠實(shí)時(shí)數(shù)據(jù)接口,僅做學(xué)習(xí)
  axios.get('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare')
   .then(data => {
   console.log("ajax返回成功");
   myData = data.data
   console.log(myData);

   })
   .catch(error => {
   console.log("ajax返回失敗");
   })
  }
  console.log(myData);
  ajax()
  setTimeout(() => {
  console.log('定時(shí)器');
  }, 2000);
  console.log(myData);
  const btn = document.querySelector('button')
  btn.onclick = () => {
  console.log("點(diǎn)擊了");
  }

null
null
ajax返回成功
Object
點(diǎn)擊了
定時(shí)器
點(diǎn)擊了

  可以看到,console在主線(xiàn)程中是同步執(zhí)行的,先執(zhí)行,而在主線(xiàn)程外的任務(wù)隊(duì)列,存放著異步執(zhí)行的內(nèi)容,這里是setTimeout,ajax和DOM事件,按照任務(wù)隊(duì)列順序執(zhí)行(循環(huán)掃描隊(duì)列)。

  為什么要循環(huán)掃描呢?

  通過(guò)點(diǎn)擊事件可以看出,當(dāng)用戶(hù)進(jìn)行交互時(shí)(點(diǎn)擊事件,滾動(dòng)事件,窗口大小變化事件等),會(huì)向事件循環(huán)中的任務(wù)隊(duì)列添加新事件,然后等待執(zhí)行,所以需要循環(huán)掃描。

二、JS異步中的回調(diào)

  既然異步都是放在最后的任務(wù)隊(duì)列執(zhí)行,那么我們很多邏輯就難以實(shí)現(xiàn),這時(shí)候我們需要處理這種異步邏輯,最常用的方式是回調(diào)——回頭調(diào)用。

回調(diào)函數(shù):簡(jiǎn)單來(lái)說(shuō)就是,函數(shù)A中傳入函數(shù)B作為參數(shù)時(shí),函數(shù)B即為A函數(shù)執(zhí)行的回調(diào)函數(shù)?;卣{(diào)有嵌套回調(diào)和鏈?zhǔn)交卣{(diào)兩種。

  下面是回調(diào)的一個(gè)簡(jiǎn)單用法:

   let myData = null
   console.log(myData);
   setTimeout(() => {
    console.log('定時(shí)器');
   }, 2000);
   const btn = document.querySelector('button')
   btn.onclick = () => {
    console.log("點(diǎn)擊了");
   }
   let name = "張三"
   function hr(callback) {
    setTimeout(() => {
     console.log(`我是${name}`);
     callback();
    }, 2001);
   }
   console.log(myData);
   function gj() {
    console.log(`${name}你好,我是李四,認(rèn)識(shí)一下吧`);
   }
   hr(gj)

null
null
點(diǎn)擊了
定時(shí)器
我是張三
張三你好,我是李四,認(rèn)識(shí)一下吧
點(diǎn)擊了

  很明顯的看到,當(dāng)我們函數(shù)需要用到數(shù)據(jù)的時(shí)候就用到了回調(diào),這里用到的是異步回調(diào)。

  回調(diào)雖然是解決異步常用的方法,可是伴隨著JS日益復(fù)雜的需求。同步異步需要越來(lái)越多的回調(diào)實(shí)現(xiàn)邏輯。同異步的混雜和過(guò)多的回調(diào)嵌套和縮進(jìn)使得代碼變得難以解讀和維護(hù),形成“回調(diào)地獄”。

  我們看一個(gè)例子:

const verifyUser = function(username, password, callback){
  dataBase.verifyUser(username, password, (error, userInfo) => {
    if (error) {
      callback(error)
    }else{
      dataBase.getRoles(username, (error, roles) => {
        if (error){
          callback(error)
        }else {
          dataBase.logAccess(username, (error) => {
            if (error){
              callback(error);
            }else{
              callback(null, userInfo, roles);
            }
          })
        }
      })
    }
  })
};

大多數(shù)人光是看到上面的代碼就感受到了腦子凍結(jié)的滋味,如果一個(gè)項(xiàng)目里擁有上百個(gè)這樣的代碼塊,過(guò)一段時(shí)間,我相信連編寫(xiě)他的人都會(huì)頭疼。來(lái)到自己的項(xiàng)目就像是來(lái)到了地獄。

  最主要的是,與此同時(shí)回調(diào)還存在信任問(wèn)題,他把執(zhí)行控制權(quán)交給了某個(gè)第三方(比如ajax)。為了解決信任問(wèn)題,我們必須在程序?qū)懜鞣N邏輯來(lái)解決回調(diào)帶來(lái)的信任問(wèn)題。

  ·調(diào)用過(guò)早

  ·調(diào)用過(guò)完

  ·調(diào)用次數(shù)過(guò)多過(guò)少,沒(méi)有把需要的參數(shù)成功傳給回調(diào)函數(shù),

  ·可能出現(xiàn)的錯(cuò)誤被吞。

  可以發(fā)現(xiàn)寫(xiě)特定邏輯來(lái)解決特定的信任問(wèn)題,已經(jīng)使得難度大于本身應(yīng)用價(jià)值了,還會(huì)造成代碼冗雜,可讀性差等問(wèn)題。

  綜上:回調(diào)解決異步存在缺陷:

     1)不符合人對(duì)任務(wù)處理的邏輯思維

     2)回調(diào)帶來(lái)的信任問(wèn)題。

  面對(duì)回調(diào)日益明顯的弊端,ES6更新了Promise用來(lái)解決異步問(wèn)題。下一篇寫(xiě)ES6——Promise。

總結(jié)

到此這篇關(guān)于JS異步的執(zhí)行原理和回調(diào)的文章就介紹到這了,更多相關(guān)JS異步執(zhí)行原理回調(diào)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 奉獻(xiàn)給JavaScript初學(xué)者的編寫(xiě)開(kāi)發(fā)的七個(gè)細(xì)節(jié)

    奉獻(xiàn)給JavaScript初學(xué)者的編寫(xiě)開(kāi)發(fā)的七個(gè)細(xì)節(jié)

    每種語(yǔ)言都有它特別的地方,對(duì)于JavaScript來(lái)說(shuō),使用var就可以聲明任意類(lèi)型的變量,這門(mén)腳本語(yǔ)言看起來(lái)很簡(jiǎn)單,然而想要寫(xiě)出優(yōu)雅的代碼卻是需要不斷積累經(jīng)驗(yàn)的。本文利列舉了JavaScript初學(xué)者應(yīng)該注意的七個(gè)細(xì)節(jié),與大家分享。
    2011-01-01
  • JS實(shí)現(xiàn)課程表小程序(仿超級(jí)課程表)加入自定義背景功能

    JS實(shí)現(xiàn)課程表小程序(仿超級(jí)課程表)加入自定義背景功能

    這篇文章主要介紹了JS實(shí)現(xiàn)課程表小程序(仿超級(jí)課程表)加入自定義背景功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • jquery和js顯示和隱藏div的幾種方法對(duì)比整理

    jquery和js顯示和隱藏div的幾種方法對(duì)比整理

    jQuery是基于JavaScript的一種框架。jQuery封裝js和Ajax的功能,提供函數(shù)接口,簡(jiǎn)化js的操作。使用jquery來(lái)顯示或者隱藏div真的很方便。
    2023-02-02
  • 微信小程序WebSocket實(shí)現(xiàn)聊天對(duì)話(huà)功能

    微信小程序WebSocket實(shí)現(xiàn)聊天對(duì)話(huà)功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序WebSocket實(shí)現(xiàn)聊天對(duì)話(huà)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • JavaScript?element的Form表單生成方式

    JavaScript?element的Form表單生成方式

    這篇文章主要介紹了JavaScript?element的Form表單生成方式,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • JS對(duì)select控件option選項(xiàng)的增刪改查示例代碼

    JS對(duì)select控件option選項(xiàng)的增刪改查示例代碼

    Javascript操作select是表單中比較常見(jiàn)的,大家可以在網(wǎng)上搜索到很多的相關(guān)資料,接下來(lái)為大家詳細(xì)介紹下,JS動(dòng)態(tài)操作select中的各種方法,感興趣的朋友可以參考下
    2013-10-10
  • JavaScript阻止事件冒泡示例分享

    JavaScript阻止事件冒泡示例分享

    這篇文章主要分享了一則JavaScript阻止事件冒泡示例,需要的朋友可以參考下
    2014-12-12
  • JS延遲加載的幾種方式小結(jié)

    JS延遲加載的幾種方式小結(jié)

    JS延遲加載,也就是等頁(yè)面加載完成之后再加載 JavaScript 文件,JS延遲加載有助于提高頁(yè)面加載速度,本文小編給大家介紹了JS延遲加載的幾種方式小結(jié),感興趣的小伙伴跟著小編一起來(lái)看看吧
    2024-08-08
  • JavaScript中分號(hào)的一些細(xì)節(jié)

    JavaScript中分號(hào)的一些細(xì)節(jié)

    這篇文章主要給大家介紹了關(guān)于JavaScript中分號(hào)的一些細(xì)節(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • window.open不被攔截的簡(jiǎn)單實(shí)現(xiàn)代碼(推薦)

    window.open不被攔截的簡(jiǎn)單實(shí)現(xiàn)代碼(推薦)

    下面小編就為大家?guī)?lái)一篇window.open不被攔截的簡(jiǎn)單實(shí)現(xiàn)代碼(推薦) 。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-08-08

最新評(píng)論

石林| 都昌县| 沂水县| 黎平县| 台安县| 西昌市| 苏尼特右旗| 安康市| 福建省| 绩溪县| 德清县| 定陶县| 昌宁县| 临潭县| 绥德县| 抚顺县| 平湖市| 杂多县| 南宁市| 余干县| 太原市| 新和县| 盐亭县| 江都市| 崇左市| 西乌珠穆沁旗| 邻水| 隆子县| 皮山县| 枞阳县| 阳西县| 泰安市| 平昌县| 革吉县| 嵊泗县| 施秉县| 泗水县| 桃源县| 盐山县| 施秉县| 宜州市|