本篇內(nèi)容主要講解“JavaScript異步怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習“JavaScript異步怎么理解”吧!
創(chuàng)新互聯(lián)公司專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、忻城網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5高端網(wǎng)站建設(shè)、成都做商城網(wǎng)站、集團公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為忻城等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
導(dǎo)讀
首先,要知道JavaScript是一門單線程的語言,要搞明白其為何會設(shè)計成單線程,要先來說一下JavaScript的最初應(yīng)用場景。
其次,在單線程語言中如何處理多線程的任務(wù)。
再次,同步和異步的流程以及如何理解異步。
然后,在解決復(fù)雜的邏輯業(yè)務(wù)時,出現(xiàn)了什么樣的問題。
再然后,怎樣解決這一問題。
=> Promise/.then(),async/await,
最后談?wù)勎⑷蝿?wù)及宏任務(wù)
JavaScript最初的應(yīng)用場景
最初,JavaScript的設(shè)計是作為瀏覽器腳本語言實現(xiàn)用戶的交互,而為了避免多線程給我們帶來很多不必要的麻煩,比如說:一個線程在刪除一個節(jié)點,而另一個線程在修改這個節(jié)點,這時我們應(yīng)該以哪一條線程為主呢?
因此,設(shè)計者將其設(shè)計成單線程的語言。
在H5中規(guī)定了JS可以擁有多個子線程,但是子線程仍然是依托于主線程的,且不能夠操作節(jié)點。
為什么要使用多線程
單線程的缺點:
單線程有一個“致命”的缺點,就是會造成阻塞;
因為是單線程,所以在程序運行時是按照先進先出的原則來進行任務(wù)處理的,也正是因如此,在主線程遇到了耗時操作后,其后的任務(wù)就進入到了等待的狀態(tài)。如果此時CPU是被占用的,也沒什么,但是如果這個耗時任務(wù)是一個不占CPU的操作,舉個栗子:向服務(wù)端請求數(shù)據(jù)。這個時候CPU出入空閑狀態(tài)但是程序并沒有執(zhí)行結(jié)束,這就形成了阻塞。
啟發(fā):
在進行耗時操作且影響代碼正常運行時,我們可以先不管這個操作,將其掛起。先處理后面的任務(wù),等到主線程清空時,再來執(zhí)行這個任務(wù)。于是出現(xiàn)了同步任務(wù)和異步任務(wù)。
同步和異步及程序運行流程
關(guān)于這一塊內(nèi)容,筆者建議從整體來看,將這一塊中的內(nèi)容結(jié)合起來讀,可能會更好理解
我們可以將同步任務(wù)理解為在主線程中執(zhí)行的任務(wù),異步任務(wù)理解為在子線程執(zhí)行。
同步任務(wù)和異步任務(wù)的執(zhí)行過程:
同步任務(wù)正常運行,沒有特殊情況會一直執(zhí)行完畢;
當主線程運行到異步任務(wù)時,會安排一個子線程去運行異步任務(wù),當異步任務(wù)運行結(jié)束后,向任務(wù)隊列發(fā)送一個事件。表示該異步任務(wù)可以進入主線程執(zhí)行了。
當不考慮下面講的微任務(wù)和宏任務(wù)時,我們的程序運行時,會先執(zhí)行同步任務(wù),執(zhí)行到異步任務(wù)后,將其發(fā)送到子線程中運行,運行結(jié)束會向任務(wù)隊列發(fā)送一個事件。同步任務(wù)執(zhí)行完畢即主線程清空后,主線程會向任務(wù)隊列詢問,是否有接收到事件,如果沒有,那么主線程會一直詢問,這個過程稱為event loop;如果有,就執(zhí)行這個事件。直到程序全部完成。
事件
在上文我們提到了事件這一概念,可以將事件理解為異步任務(wù)返回的一個回調(diào)函數(shù),這個回調(diào)函數(shù)也就是事件會在主線程上運行。異步任務(wù)必須有回調(diào)函數(shù)。
拓展:異步函數(shù)必須return一個Promise對象
關(guān)于事件,阮一峰前輩是這么寫的:
"任務(wù)隊列"中的事件,除了IO設(shè)備的事件以外,還包括一些用戶產(chǎn)生的事件(比如鼠標點擊、頁面滾動等等)。只要指定過回調(diào)函數(shù),這些事件發(fā)生時就會進入"任務(wù)隊列",等待主線程讀取。
“回調(diào)地獄”
在實際開發(fā)中,為了實現(xiàn)一些邏輯需求,可能會用到多層回調(diào)函數(shù)嵌套。這個時候會導(dǎo)致代碼的可讀性很差。人們稱之為“回調(diào)地獄”
Promise對象
代表的是異步操作 最終完成或失敗
目的:將回調(diào)函數(shù)的多層嵌套形式,拆解成鏈式調(diào)用的形式。
本質(zhì):函數(shù)返回的對象,在這個對象上綁定回調(diào)函數(shù),避免從一開始將回調(diào)函數(shù)作為參數(shù)傳入上一層函數(shù)。
一個Promise必然會處于這幾種狀態(tài):
待定(pending):初始狀態(tài),既沒有被兌現(xiàn),也沒有被拒絕
已兌現(xiàn)(fulfilled):意味著操作成功完成 resolve
已拒絕(rejected):意味著操作失敗 reject
Promise的使用:一般作為函數(shù)的返回值
const fn = function(){
return new Promise((resolve,reject)=>{
if(ture){
resolve(a);
}else{
reject(b);
}
})
}
fn()
.then((res)=>{有返回值的函數(shù)})
.then((res)=>{有返回值的函數(shù)})
.then((res)=>{有返回值的函數(shù)})
…
.then(res=>{最后的函數(shù)})
// 如果Promise對象中的請求完成了,那么將resolve的值傳給then中的回調(diào)函數(shù)作為參數(shù)執(zhí)行then方法
// 可以附加 .catch()在鏈式結(jié)構(gòu)的末尾,來捕獲錯誤(reject傳回的值),并且之后的then不會執(zhí)行
// 可以在最后加一個 .finally() 來執(zhí)行清理操作 并且這個方法不管請求成功與否都會執(zhí)行
async/await
是Promise的語法糖;讓繁瑣的then(),和冗長的鏈式調(diào)用可讀性變得更長些;
具體使用方式:
//異步函數(shù)1
function getData(data){
return new Promise((reslove)=>{
reslove(data)
})
}
//異步函數(shù)2
function sayHello(data){
return new Promise((reslove)=>{
reslove(data)
})
}
//異步函數(shù)
async function fn(){
// await相當于。then() getData()相當于是回調(diào)函數(shù)
// await必須在async修飾的函數(shù)體內(nèi)使用
const promiseA = await getData('info')
const promiseB = await sayHello(promiseA);
console.log(promiseB)
}
談?wù)勎⑷蝿?wù)和宏任務(wù)
微任務(wù)
注意:Promise對象中的代碼是同步的,then()方法中的回調(diào)函數(shù)才是異步的
then()中的是微任務(wù)
宏任務(wù)
定時器是宏任務(wù)
代碼執(zhí)行順序口訣:先同步后異步,先微任務(wù)后宏任務(wù)
總之,同微宏
到此,相信大家對“JavaScript異步怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習!
文章標題:JavaScript異步怎么理解
瀏覽路徑:http://vcdvsql.cn/article0/pdcooo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護、電子商務(wù)、品牌網(wǎng)站設(shè)計、網(wǎng)頁設(shè)計公司、手機網(wǎng)站建設(shè)、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)