亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

事件循環(huán)

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

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

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

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

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

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

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

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

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

任務(wù)隊(duì)列

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

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

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

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

可能你認(rèn)為這里會(huì)打印出ABCD,但其實(shí)打印結(jié)果是ACDB,因?yàn)槎〞r(shí)器觸發(fā)是在所有同步事件隊(duì)列清空之后才開始執(zhí)行的。

回調(diào)

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

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

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

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

嵌套回調(diào)

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

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

promise

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

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

promise調(diào)度技巧

如果兩個(gè)promise都已經(jīng)決議,那么p1.then和p2.then應(yīng)該最終會(huì)先調(diào)用p1的回調(diào),然后是p2的哪些,但還有一些可能微妙的場景:

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

這里的輸出結(jié)果是 A B C

一個(gè)promise決議后,這個(gè)promise上所有的通過then注冊的回調(diào)都會(huì)在下一個(gè)異步時(shí)機(jī)點(diǎn)上一次調(diào)用。所以在這里'C'無法搶占或打斷‘B’,因?yàn)檫@是promise的運(yùn)作方式。

錯(cuò)誤處理

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

function(){
  setTimeout(()=>{
    bar()
  },1000)
}
try{
  foo()
}catch(err){
   //永遠(yuǎn)不會(huì)到達(dá)這里
}

try...catch當(dāng)然很好,但是無法跨越異步操作工作,所以catch無法攔截定時(shí)器內(nèi)異步的錯(cuò)誤。

方法1. 可以在then(resolve,reject)中第二個(gè)回調(diào)內(nèi)處理錯(cuò)誤,可以throw傳遞一個(gè)error。

方法2. finally捕獲

不管promise最后的狀態(tài),在執(zhí)行完then或catch指定的回調(diào)函數(shù)之后,都會(huì)執(zhí)行finally方法指定的回調(diào)函數(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") //會(huì)打印的!
   })

promise.all([...])

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

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

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

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

promise.race([...])

盡管promise.all協(xié)調(diào)多個(gè)并發(fā)promise的運(yùn)行,并假定所有都需要完成,但有時(shí)候你會(huì)只想響應(yīng)第一個(gè)完成promise的結(jié)果,并直接拋棄其他promise。

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

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

(如果你傳入一個(gè)空數(shù)組,那race永遠(yuǎn)不會(huì)resolve,永遠(yuǎn)不要傳遞空數(shù)組)

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

因?yàn)橹挥幸粋€(gè)promise能夠取勝,所以完成值是單個(gè)消息,而不是像all一樣是一個(gè)數(shù)組。

all和race的變體

· none([...])

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

· any([...])

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

· first([...])

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

· last([...])

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

無法取消的promise

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

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

相關(guān)文章

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

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

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

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

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

    對Layer彈窗使用及返回?cái)?shù)據(jù)接收的實(shí)例詳解

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

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

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

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

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

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

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

    移動(dòng)端界面的適配

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

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

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

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

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

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

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

最新評論