這篇文章將為大家詳細(xì)講解有關(guān)javascript異步的作用,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
我們提供的服務(wù)有:成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、巴中ssl等。為成百上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的巴中網(wǎng)站制作公司什么是js異步?我們知道JavaScript的單線程的,這與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動(dòng),以及操作DOM。這決定了它只能是單線程,否則會(huì)帶來很復(fù)雜的同步問題。比如,假定JavaScript同時(shí)有兩個(gè)線程,一個(gè)線程在某個(gè)DOM節(jié)點(diǎn)上添加內(nèi)容,另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器應(yīng)該以哪個(gè)線程為準(zhǔn)?
所謂"單線程",就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。
這種模式的好處是實(shí)現(xiàn)起來比較簡(jiǎn)單,執(zhí)行環(huán)境相對(duì)單純;壞處是只要有一個(gè)任務(wù)耗時(shí)很長(zhǎng),后面的任務(wù)都必須排隊(duì)等著,會(huì)拖延整個(gè)程序的執(zhí)行。常見的瀏覽器無響應(yīng)(假死),往往就是因?yàn)槟骋欢蜫avascript代碼長(zhǎng)時(shí)間運(yùn)行(比如死循環(huán)),導(dǎo)致整個(gè)頁面卡在這個(gè)地方,其他任務(wù)無法執(zhí)行。
ajax的同步請(qǐng)求就會(huì)導(dǎo)致瀏覽器產(chǎn)生假死,因?yàn)樗鼤?huì)鎖定瀏覽器的UI(按鈕,菜單,滾動(dòng)條等),并阻塞所有用戶的交互,jquery中的ajax有這樣一個(gè)同步請(qǐng)求的功能,一定要慎用,尤其是在請(qǐng)求的數(shù)據(jù)量很大的時(shí)候,要避免使用同步請(qǐng)求。
舉幾個(gè)栗子感受一下異步
后臺(tái)接口使用easy-mock,官方地址:https://easy-mock.com/
ajax使用axios,基本代碼如下
javascript異步
我們通過添加一些js來看下效果,
異步-定時(shí)器console.log(myData); setTimeout(() => { console.log('定時(shí)器'); }, 2000); console.log(myData);
輸出,應(yīng)該沒什么懸念
//null //null //定時(shí)器
執(zhí)行順序:
先執(zhí)行第一個(gè) console.log(myData);
然后遇到了定時(shí)器,將定時(shí)器掛起(就是暫停了這個(gè)定時(shí)器)
繼續(xù)執(zhí)行第二個(gè) console.log(myData);
沒有可以執(zhí)行的js代碼,回頭把掛起的任務(wù)繼續(xù)執(zhí)行下去
繼續(xù)看下一個(gè)栗子
console.log(myData); ajax() console.log(myData);
看下輸出,依然沒有懸念
//null //null //ajax返回成功 //{success: true, data: {…}}(這是接口返回的數(shù)據(jù),我們不必關(guān)心返回的具體內(nèi)容,只要知道返回了就好,陌上寒注)
執(zhí)行順序和上面的定時(shí)器基本類似,不在此贅述。
將兩個(gè)栗子合并,我們看下
console.log(myData); ajax() setTimeout(() => { console.log('定時(shí)器'); }, 2000); console.log(myData);
輸出,
//null //null //ajax返回成功 //{success: true, data: {…}} //定時(shí)器
發(fā)現(xiàn)問題了嗎??jī)蓚€(gè)異步函數(shù)相遇了,先執(zhí)行誰?誰跑的快就先執(zhí)行誰?
也可以這么說,其實(shí)這引發(fā)了另外一個(gè)知識(shí)點(diǎn),
兩個(gè) console.log(myData);是同步執(zhí)行的,他們都在js的主線程上執(zhí)行,
在主線程之外還存在一個(gè)任務(wù)隊(duì)列,任務(wù)隊(duì)列中存放著需要異步執(zhí)行的內(nèi)容
當(dāng)主線程運(yùn)行完畢之后,就會(huì)去執(zhí)行任務(wù)隊(duì)列中的任務(wù)(不斷的重復(fù)掃描)直到任務(wù)隊(duì)列清空
觀察這段代碼
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,為什么會(huì)這樣?
console.log(2);在主線程中,先執(zhí)行,
setTimeout(function(){console.log(1);}, 0);放在了任務(wù)隊(duì)列中,
只有在主線程執(zhí)行完了才會(huì)去執(zhí)行任務(wù)列隊(duì)中的內(nèi)容
看這段代碼,有助于你的理解
console.log(myData); ajax() setTimeout(() => { console.log('定時(shí)器'); }, 2000); console.log(myData); const btn = document.querySelector('button') btn.onclick = () => { console.log("點(diǎn)擊了"); }
我們?yōu)閎utton按鈕添加了點(diǎn)擊事件,在瀏覽器刷新的同時(shí)不停地對(duì)按鈕進(jìn)行點(diǎn)擊操作(當(dāng)然是手動(dòng)點(diǎn)擊)
看下輸出:
//null //null //(10次輸出)點(diǎn)擊了 //ajax返回成功 //{success: true, data: {…}} //定時(shí)器 //點(diǎn)擊了
這樣是不是可以理解為什么主線程要去循環(huán)掃描任務(wù)列隊(duì)了?
事件循環(huán)的每一輪稱為一個(gè)tick(有沒有聯(lián)想到vue中的nextTick?)
當(dāng)產(chǎn)生用戶交互(鼠標(biāo)點(diǎn)擊事件,頁面滾動(dòng)事件,窗口大小變化事件等等),ajax,定時(shí)器,計(jì)時(shí)器等,會(huì)向事件循環(huán)中的任務(wù)隊(duì)列添加事件,然后等待執(zhí)行,
定時(shí)任務(wù):setTimeout,setInverval
網(wǎng)絡(luò)請(qǐng)求:ajax請(qǐng)求,img圖片的動(dòng)態(tài)加載
事件綁定或者叫DOM事件,比如一個(gè)點(diǎn)擊事件,我不知道它什么時(shí)候點(diǎn),但是在它點(diǎn)擊之前,我該干什么還是干什么。用addEventListener注冊(cè)一個(gè)類型的事件的時(shí)候,瀏覽器會(huì)有一個(gè)單獨(dú)的模塊去接收這個(gè)東西,當(dāng)事件被觸發(fā)的時(shí)候,瀏覽器的某個(gè)模塊,會(huì)把相應(yīng)的函數(shù)扔到異步隊(duì)列中,如果現(xiàn)在執(zhí)行棧中是空的,就會(huì)直接執(zhí)行這個(gè)函數(shù)。
ES6中的Promise
在可能發(fā)生等待的情況
等待過程中不能像alert一樣阻塞程序的時(shí)候
因此,所有的“等待的情況”都需要異步
一句話總結(jié)就是需要等待但是又不能阻塞程序的時(shí)候需要使用異步
異步和并行千萬不要把異步和并行搞混了,
異步是單線程的,并行是多線程的
異步:主線程的任務(wù)以同步的方式執(zhí)行完畢,才會(huì)去依次執(zhí)行任務(wù)列隊(duì)中的異步任務(wù)
并行:兩個(gè)或多個(gè)事件鏈隨時(shí)間發(fā)展交替執(zhí)行,以至于從更高的層次來看,就像是同時(shí)在運(yùn)行(盡管在任意時(shí)刻只處理一個(gè)事件)
關(guān)于javascript異步的作用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。