欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文了解你不知道的JavaScript異步篇

 更新時間:2022年11月09日 10:31:40   作者:霍格沃茨魔法師  
這篇文章主要為大家詳細介紹了一些你不知道的JavaScript異步相關知識,文中的示例代碼講解詳細,對我們學習JavaScript有一定幫助,感興趣的可以跟隨小編一起學習一下

事件循環(huán)

先通過一段偽代碼了解一下事件循環(huán)這個概念

//eventLoop是一個用作隊列的數(shù)組
var eventLoop = []
var event;
//永遠執(zhí)行
while(true){
   if(eventLoop.length>0){}
    //拿到隊列中的下一個事件
    event = eventLoop.shift();
    //現(xiàn)在,執(zhí)行下一個事件
    try{
      event()
    }
    catch(err){
     reportError(err)
    }
}

這是一段繼續(xù)簡化的代碼,你可以看到有一個用while循環(huán)實現(xiàn)的持續(xù)運行的循環(huán),循環(huán)的每一輪稱為一個tick。對每個tick而言,如果在隊列中有等待事件,就會從隊列中摘下一個事件并執(zhí)行,這些事件就是所謂的回調函數(shù)。

一定要清楚,setTimeout()并沒有把你的回調函數(shù)掛在事件循環(huán)隊列中。他所做的是設定一個定時器。當定時器到時后,環(huán)境會把你的回調函數(shù)放在事件循環(huán)中,這樣,在未來某個時刻的tick會摘下并執(zhí)行這個回調。所以這也是為什么setTimeout時間精度可能不太高,它只能確保你的回調函數(shù)不會在指定的時間間隔之前運行,但可能會在事件循環(huán)隊列中20個項目后才執(zhí)行。取決于你事件隊列的項目與狀態(tài),畢竟JavaScript一次只能處理一個事件。這也引出了另一個概念“并發(fā)”。

當兩個或多個“進程”同時執(zhí)行就出現(xiàn)了并發(fā),也許瀏覽器會發(fā)出很多請求,當發(fā)出第二個請求時,第一個請求返回響應,當發(fā)出第三個請求時,第二個請求返回響應。這里請求2與響應1并發(fā)運行,請求3與響應2并發(fā)運行,但是他們的各個事件是在事件循環(huán)隊列中依次運行的。

更常見一點的情況是,并發(fā)的“進程”需要相互交流,如果出現(xiàn)這樣的交互,就需要對他們的交互進行協(xié)作以避免競態(tài)的出現(xiàn)。下面是兩個并發(fā)的進程通過隱含的順序相互影響,這個順序有時會被破壞:

var res = [];
function response(data){
    res.push(data)
}
ajax("http://url1",response);
ajax("http://url2",response);

這里的兩個ajax去調用response函數(shù),但不確定哪一會先執(zhí)行完成,這種不確定性很有可能就是一個競態(tài)條件bug。

在es6中,有一個新的概念建立在事件循環(huán)隊列之上,解決這種不確定性的執(zhí)行,叫做任務隊列

任務隊列

對任務隊列最好的理解方式就是,它是掛在事件循環(huán)隊列的每個tick之后的一個隊列。在事件循環(huán)的每個tick中??赡艹霈F(xiàn)的異步動作不會導致一個完整的新事件添加到事件循環(huán)隊列中,而會在當前tick的任務隊列末尾添加一個任務。

任務隊列意思是:哦?原來這里還有一件事情要做,但要在任何事情發(fā)生之前就完成它,立刻接著執(zhí)行它。

而事件循環(huán)類似于做完這件事情,需要重新到隊尾排隊才能再做這件事情。

console.log("A")
setTimeout(()=>{
    console.log("B")
},0)
task(()=>{
console.log("C")
    task(()=>{
      console.log('D')
    })
})

可能你認為這里會打印出ABCD,但其實打印結果是ACDB,因為定時器觸發(fā)是在所有同步事件隊列清空之后才開始執(zhí)行的。

回調

到目前位置,回調是編寫和處理JavaScript程序異步邏輯的最常用的方式,也是最基礎的異步模式。

我們的大腦可以看作類似于單線程運行的事件循環(huán)隊列,就像JavaScript引擎那樣。用正在寫博客的我寫作進行類比。此刻我心里就是計劃寫啊寫一直寫,一次完成我腦海中已經按順序排好的一系列要點。我沒有將任何終端或非線性的行為納入到我的寫作計劃中。然而盡管如此,實際上我的大腦還是在不停的切換狀態(tài)。即使我的大腦在以異步事件方式運行,但我的寫作還是以順序、同步的進行,“先寫這里,再寫那里”。

所以,如果說同步的大腦計劃能夠很好地映射到同步代碼語句,那么我們大腦在規(guī)劃異步方面又是怎樣的呢?

答案是回調。即使在腦海中有許多事件出現(xiàn),如果真的想到什么就做什么去那恐怕我這篇博客也無法完成。但在實際執(zhí)行方面,我的大腦就是這樣運作了。不是多任務,而是快速的上下文切換。

嵌套回調

listen("click",()=>{
    setTimeout(()=>{
     setTimeout(()=>{
       ajax("http:url",()=>{
          console.log("響應結果")
       })
    },1000)
},1000)
})

你可能非常熟悉這樣的代碼,好幾個函數(shù)嵌套在一起構成的鏈,這種代碼常常被稱為回調地獄問題,在大型項目中他引起的問題要比這些嚴重得多。為了避免回調地獄問題,產生了偉大的promise。

promise

在promise中,傳入的函數(shù)會立刻執(zhí)行,它有兩個參數(shù),在本例中我們將其分別稱為resolve和reject。前者代表完成,后者代表拒絕。

new Promise((resolve,reject)=>{
   //最終調用resolve還是reject
}).then(
  function(){
   console.log("then")
  }
)

promise調度技巧

如果兩個promise都已經決議,那么p1.then和p2.then應該最終會先調用p1的回調,然后是p2的哪些,但還有一些可能微妙的場景:

p.then(function(){
  p.then(function(){
    console.log("C")
  })
  console.log("A")
})
p.then(function(){
   console.log("B")
})

這里的輸出結果是 A B C

一個promise決議后,這個promise上所有的通過then注冊的回調都會在下一個異步時機點上一次調用。所以在這里'C'無法搶占或打斷‘B’,因為這是promise的運作方式。

錯誤處理

對于大多數(shù)開發(fā)者來說,最自然的錯誤處理就是try...catch結構,遺憾的是它只能是同步的,無法用于異步代碼模式。

function(){
  setTimeout(()=>{
    bar()
  },1000)
}
try{
  foo()
}catch(err){
   //永遠不會到達這里
}

try...catch當然很好,但是無法跨越異步操作工作,所以catch無法攔截定時器內異步的錯誤。

方法1. 可以在then(resolve,reject)中第二個回調內處理錯誤,可以throw傳遞一個error。

方法2. finally捕獲

不管promise最后的狀態(tài),在執(zhí)行完then或catch指定的回調函數(shù)之后,都會執(zhí)行finally方法指定的回調函數(shù)。

function fn(val){
    return new Promise((resolve,reject)=>{
        if(val){
          resolve({name:"111"})
        }else{
          reject("404")
        }
    })
}
//執(zhí)行函數(shù)
fn(true)
   .then(data=>{
     console.log(data) //打印name:111鍵值對
     return fn(false)
   })
   .catch(e=>{
     console.log(e) //打印404
     return fn(false)
   })
   .finally(()=>{
     console.log("finally") //會打印的!
   })

promise.all([...])

假如你想同時發(fā)送兩個請求,等他們不管以什么順序完成之后再發(fā)送第三個請求

Promise.all([p1,p2])
.then(function(){
    return request("http:url3")
})
.then(function(msg){
  console.log(msg)
})

Promise.all需要一個參數(shù),是一個數(shù)組,通常由promise實例組成,從promise.all調用返回的promise會收到一個完整消息(msg)。這是一個由數(shù)組完成后傳入的消息,與順序無關。

另外,當數(shù)組內有且僅有所有成員promise都完成后才算完成。如果這些promise有任何一個被拒絕那all就會立刻被拒絕,并丟棄已經成功的來自其他數(shù)組成員的promise結果。

promise.race([...])

盡管promise.all協(xié)調多個并發(fā)promise的運行,并假定所有都需要完成,但有時候你會只想響應第一個完成promise的結果,并直接拋棄其他promise。

這種在promise中被稱之為競態(tài)。

promise.race()也接受一個數(shù)組做參數(shù)。這個數(shù)組有一個/多個promise組成。一旦有任何一個promise為成功resolve,promise.race()就會完成;一旦有任何一個為reject被拒絕,它就會拒絕。

(如果你傳入一個空數(shù)組,那race永遠不會resolve,永遠不要傳遞空數(shù)組)

Promise.race([p1,p2])
.then(function(){
//p1和p2其中之一會完成這場競賽,突破重圍
    return request("http:url3")
})
.then(function(msg){
  console.log(msg)
})

因為只有一個promise能夠取勝,所以完成值是單個消息,而不是像all一樣是一個數(shù)組。

all和race的變體

· none([...])

這個模式類似于all([...]),不過完成和拒絕的情況互換了,而是所有的promise都要被拒絕,即拒絕轉化為完成值。

· any([...])

這個模式與all([...])類似,但是會忽略拒絕,所以只需要完成一個而不是全部。

· first([...])

這個模式類似于與any([...])的競爭,即只要第一個promise完成,就會忽略后續(xù)的任何完成和拒絕。

· last([...])

這個模式類似于first([...]),但卻是只有最后一個完成勝出。

無法取消的promise

一旦創(chuàng)建了一個promise并為其注冊了完成/拒絕的處理函數(shù),如果出現(xiàn)某種情況使得這個任務懸而未決的話,你也沒有辦法從外部停止它的進程。

以上就是一文了解你不知道的JavaScript異步篇的詳細內容,更多關于JavaScript異步的資料請關注腳本之家其它相關文章!

相關文章

  • JavaScript中數(shù)字轉字符串的6種方式以及性能比較

    JavaScript中數(shù)字轉字符串的6種方式以及性能比較

    在JavaScript中將字符串轉換為數(shù)字有多種方法,下面這篇文章主要給大家介紹了關于JavaScript中數(shù)字轉字符串的6種方式以及性能比較的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04
  • 微信小程序用戶授權環(huán)節(jié)實現(xiàn)過程

    微信小程序用戶授權環(huán)節(jié)實現(xiàn)過程

    這篇文章主要介紹了微信小程序用戶授權環(huán)節(jié)實現(xiàn)過程,在商城項目中,我們需要對部分的頁面,進行一個授權的判別,例如購物車,及個人中心,需要完成用戶信息的授權后,獲取到相關信息
    2023-01-01
  • 對Layer彈窗使用及返回數(shù)據(jù)接收的實例詳解

    對Layer彈窗使用及返回數(shù)據(jù)接收的實例詳解

    今天小編就為大家分享一篇對Layer彈窗使用及返回數(shù)據(jù)接收的實例詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • JAVA中截取字符串substring用法詳解

    JAVA中截取字符串substring用法詳解

    這篇文章主要介紹了JAVA截取字符串 substring方法,要的朋友可以參考下
    2017-04-04
  • JavaScript實現(xiàn)頁面跳轉的八種方式

    JavaScript實現(xiàn)頁面跳轉的八種方式

    這篇文章介紹了JavaScript實現(xiàn)頁面跳轉的八種方式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • js自調用匿名函數(shù)的三種寫法(推薦)

    js自調用匿名函數(shù)的三種寫法(推薦)

    下面小編就為大家?guī)硪黄猨s自調用匿名函數(shù)的三種寫法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • 移動端界面的適配

    移動端界面的適配

    本文主要介紹了移動端頁面適配相關知識,用于解決在所有手機上看到字體的大小都一樣問題。下面跟著小編一起來看下吧
    2017-01-01
  • JS設計模式之狀態(tài)模式的用法使用方法

    JS設計模式之狀態(tài)模式的用法使用方法

    JavaScript狀態(tài)模式是一種行為型設計模式,核心是對象在其內部狀態(tài)改變時改變其行為,狀態(tài)模式將對象的行為封裝到不同的狀態(tài)類中,使得對象在不同狀態(tài)下可以選擇不同的行為,本文給大家詳細的介紹一下狀態(tài)設計模式在Js中的使用,需要的朋友可以參考下
    2023-08-08
  • javascript實現(xiàn)自由編輯圖片代碼詳解

    javascript實現(xiàn)自由編輯圖片代碼詳解

    這篇文章主要介紹了javascript實現(xiàn)自由編輯圖片代碼詳解,在當下的的前端項目中,圖片功能可以說是非常常見的,圖片的展示、圖片的裁剪編輯、圖片的上傳等,那么我們的項目便來了個需求。,需要的朋友可以參考下
    2019-06-06
  • 微信小程序日期時間選擇器使用方法

    微信小程序日期時間選擇器使用方法

    這篇文章主要為大家詳細介紹了微信小程序日期時間選擇器的使用方法,自定義精確到分秒或時段,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02

最新評論