溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

javascript異步的作用

發(fā)布時間:2020-12-05 11:24:51 來源:億速云 閱讀:173 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)javascript異步的作用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

什么是js異步?

我們知道JavaScript的單線程的,這與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器應(yīng)該以哪個線程為準(zhǔn)?
所謂"單線程",就是指一次只能完成一件任務(wù)。如果有多個任務(wù),就必須排隊,前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù),以此類推。
這種模式的好處是實現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純;壞處是只要有一個任務(wù)耗時很長,后面的任務(wù)都必須排隊等著,會拖延整個程序的執(zhí)行。常見的瀏覽器無響應(yīng)(假死),往往就是因為某一段Javascript代碼長時間運(yùn)行(比如死循環(huán)),導(dǎo)致整個頁面卡在這個地方,其他任務(wù)無法執(zhí)行。
ajax的同步請求就會導(dǎo)致瀏覽器產(chǎn)生假死,因為它會鎖定瀏覽器的UI(按鈕,菜單,滾動條等),并阻塞所有用戶的交互,jquery中的ajax有這樣一個同步請求的功能,一定要慎用,尤其是在請求的數(shù)據(jù)量很大的時候,要避免使用同步請求。
舉幾個栗子感受一下異步
后臺接口使用easy-mock,官方地址:https://easy-mock.com/
ajax使用axios,基本代碼如下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>javascript異步</title>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>
  <button>點擊</button>
  <script>
    {
      let myData = null
      //ajax請求
      function ajax() {
        axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
          .then(data => {
            console.log("ajax返回成功");// handle success
            myData = data.data
            console.log(myData);

          })
          .catch(error => {
            // console.log(error); // handle error
            console.log("ajax返回失敗");
          })
      }
    }
  </script>
</body>
</html>

我們通過添加一些js來看下效果,

異步-定時器
      console.log(myData);
      setTimeout(() => {
        console.log('定時器');
      }, 2000);
      console.log(myData);

輸出,應(yīng)該沒什么懸念

//null
//null
//定時器

執(zhí)行順序:
先執(zhí)行第一個 console.log(myData);
然后遇到了定時器,將定時器掛起(就是暫停了這個定時器)
繼續(xù)執(zhí)行第二個 console.log(myData);
沒有可以執(zhí)行的js代碼,回頭把掛起的任務(wù)繼續(xù)執(zhí)行下去
繼續(xù)看下一個栗子

異步-ajax
      console.log(myData);
      ajax()
      console.log(myData);

看下輸出,依然沒有懸念

//null
//null
//ajax返回成功
//{success: true, data: {…}}(這是接口返回的數(shù)據(jù),我們不必關(guān)心返回的具體內(nèi)容,只要知道返回了就好,陌上寒注)

執(zhí)行順序和上面的定時器基本類似,不在此贅述。
將兩個栗子合并,我們看下

      console.log(myData);
      ajax()
      setTimeout(() => {
        console.log('定時器');
      }, 2000);
      console.log(myData);

輸出,

//null
//null
//ajax返回成功
//{success: true, data: {…}}
//定時器

發(fā)現(xiàn)問題了嗎?兩個異步函數(shù)相遇了,先執(zhí)行誰?誰跑的快就先執(zhí)行誰?
也可以這么說,其實這引發(fā)了另外一個知識點,

任務(wù)隊列和事件循環(huán)

兩個  console.log(myData);是同步執(zhí)行的,他們都在js的主線程上執(zhí)行,
在主線程之外還存在一個任務(wù)隊列,任務(wù)隊列中存放著需要異步執(zhí)行的內(nèi)容
當(dāng)主線程運(yùn)行完畢之后,就會去執(zhí)行任務(wù)隊列中的任務(wù)(不斷的重復(fù)掃描)直到任務(wù)隊列清空

觀察這段代碼

      console.log(1);
      setTimeout(function () {
        console.log(2);
      }, 1000);
      console.log(3);

輸出:1,3,2,這沒什么可解釋的
再看一段代碼

setTimeout(function(){console.log(1);}, 0);
console.log(2);

輸出:2,1,為什么會這樣?
console.log(2);在主線程中,先執(zhí)行,
setTimeout(function(){console.log(1);}, 0);放在了任務(wù)隊列中,
只有在主線程執(zhí)行完了才會去執(zhí)行任務(wù)列隊中的內(nèi)容

為什么主線程的任務(wù)執(zhí)行完了后需要不斷的掃描任務(wù)列隊中的內(nèi)容呢?

看這段代碼,有助于你的理解

      console.log(myData);
      ajax()
      setTimeout(() => {
        console.log('定時器');
      }, 2000);
      console.log(myData);
      const btn = document.querySelector('button')
      btn.onclick = () => {
        console.log("點擊了");
      }

我們?yōu)閎utton按鈕添加了點擊事件,在瀏覽器刷新的同時不停地對按鈕進(jìn)行點擊操作(當(dāng)然是手動點擊)
看下輸出:

//null
//null
//(10次輸出)點擊了
//ajax返回成功
//{success: true, data: {…}}
//定時器
//點擊了

這樣是不是可以理解為什么主線程要去循環(huán)掃描任務(wù)列隊了?
事件循環(huán)的每一輪稱為一個tick(有沒有聯(lián)想到vue中的nextTick?)
當(dāng)產(chǎn)生用戶交互(鼠標(biāo)點擊事件,頁面滾動事件,窗口大小變化事件等等),ajax,定時器,計時器等,會向事件循環(huán)中的任務(wù)隊列添加事件,然后等待執(zhí)行,

前端異步有哪些場景?

  1. 定時任務(wù):setTimeout,setInverval

  2. 網(wǎng)絡(luò)請求:ajax請求,img圖片的動態(tài)加載

  3. 事件綁定或者叫DOM事件,比如一個點擊事件,我不知道它什么時候點,但是在它點擊之前,我該干什么還是干什么。用addEventListener注冊一個類型的事件的時候,瀏覽器會有一個單獨的模塊去接收這個東西,當(dāng)事件被觸發(fā)的時候,瀏覽器的某個模塊,會把相應(yīng)的函數(shù)扔到異步隊列中,如果現(xiàn)在執(zhí)行棧中是空的,就會直接執(zhí)行這個函數(shù)。

  4. ES6中的Promise

什么時候需要異步:

  1. 在可能發(fā)生等待的情況

  2. 等待過程中不能像alert一樣阻塞程序的時候

  3. 因此,所有的“等待的情況”都需要異步

一句話總結(jié)就是需要等待但是又不能阻塞程序的時候需要使用異步

異步和并行

千萬不要把異步和并行搞混了,
異步是單線程的,并行是多線程的
異步:主線程的任務(wù)以同步的方式執(zhí)行完畢,才會去依次執(zhí)行任務(wù)列隊中的異步任務(wù)
并行:兩個或多個事件鏈隨時間發(fā)展交替執(zhí)行,以至于從更高的層次來看,就像是同時在運(yùn)行(盡管在任意時刻只處理一個事件)

關(guān)于javascript異步的作用就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI