您好,登錄后才能下訂單哦!
本篇內容主要講解“JavaScript異步怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JavaScript異步怎么理解”吧!
導讀
首先,要知道JavaScript是一門單線程的語言,要搞明白其為何會設計成單線程,要先來說一下JavaScript的最初應用場景。
其次,在單線程語言中如何處理多線程的任務。
再次,同步和異步的流程以及如何理解異步。
然后,在解決復雜的邏輯業務時,出現了什么樣的問題。
再然后,怎樣解決這一問題。
=> Promise/.then(),async/await,
最后談談微任務及宏任務
JavaScript最初的應用場景
最初,JavaScript的設計是作為瀏覽器腳本語言實現用戶的交互,而為了避免多線程給我們帶來很多不必要的麻煩,比如說:一個線程在刪除一個節點,而另一個線程在修改這個節點,這時我們應該以哪一條線程為主呢?
因此,設計者將其設計成單線程的語言。
在H5中規定了JS可以擁有多個子線程,但是子線程仍然是依托于主線程的,且不能夠操作節點。
為什么要使用多線程
單線程的缺點:
單線程有一個“致命”的缺點,就是會造成阻塞;
因為是單線程,所以在程序運行時是按照先進先出的原則來進行任務處理的,也正是因如此,在主線程遇到了耗時操作后,其后的任務就進入到了等待的狀態。如果此時CPU是被占用的,也沒什么,但是如果這個耗時任務是一個不占CPU的操作,舉個栗子:向服務端請求數據。這個時候CPU出入空閑狀態但是程序并沒有執行結束,這就形成了阻塞。
啟發:
在進行耗時操作且影響代碼正常運行時,我們可以先不管這個操作,將其掛起。先處理后面的任務,等到主線程清空時,再來執行這個任務。于是出現了同步任務和異步任務。
同步和異步及程序運行流程
關于這一塊內容,筆者建議從整體來看,將這一塊中的內容結合起來讀,可能會更好理解
我們可以將同步任務理解為在主線程中執行的任務,異步任務理解為在子線程執行。
同步任務和異步任務的執行過程:
同步任務正常運行,沒有特殊情況會一直執行完畢;
當主線程運行到異步任務時,會安排一個子線程去運行異步任務,當異步任務運行結束后,向任務隊列發送一個事件。表示該異步任務可以進入主線程執行了。
當不考慮下面講的微任務和宏任務時,我們的程序運行時,會先執行同步任務,執行到異步任務后,將其發送到子線程中運行,運行結束會向任務隊列發送一個事件。同步任務執行完畢即主線程清空后,主線程會向任務隊列詢問,是否有接收到事件,如果沒有,那么主線程會一直詢問,這個過程稱為event loop;如果有,就執行這個事件。直到程序全部完成。
事件
在上文我們提到了事件這一概念,可以將事件理解為異步任務返回的一個回調函數,這個回調函數也就是事件會在主線程上運行。異步任務必須有回調函數。
拓展:異步函數必須return一個Promise對象
關于事件,阮一峰前輩是這么寫的:
"任務隊列"中的事件,除了IO設備的事件以外,還包括一些用戶產生的事件(比如鼠標點擊、頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。
“回調地獄”
在實際開發中,為了實現一些邏輯需求,可能會用到多層回調函數嵌套。這個時候會導致代碼的可讀性很差。人們稱之為“回調地獄”
Promise對象
代表的是異步操作 最終完成或失敗
目的:將回調函數的多層嵌套形式,拆解成鏈式調用的形式。
本質:函數返回的對象,在這個對象上綁定回調函數,避免從一開始將回調函數作為參數傳入上一層函數。
一個Promise必然會處于這幾種狀態:
待定(pending):初始狀態,既沒有被兌現,也沒有被拒絕
已兌現(fulfilled):意味著操作成功完成 resolve
已拒絕(rejected):意味著操作失敗 reject
Promise的使用:一般作為函數的返回值
const fn = function(){
return new Promise((resolve,reject)=>{
if(ture){
resolve(a);
}else{
reject(b);
}
})
}
fn()
.then((res)=>{有返回值的函數})
.then((res)=>{有返回值的函數})
.then((res)=>{有返回值的函數})
…
.then(res=>{最后的函數})
// 如果Promise對象中的請求完成了,那么將resolve的值傳給then中的回調函數作為參數執行then方法
// 可以附加 .catch()在鏈式結構的末尾,來捕獲錯誤(reject傳回的值),并且之后的then不會執行
// 可以在最后加一個 .finally() 來執行清理操作 并且這個方法不管請求成功與否都會執行
async/await
是Promise的語法糖;讓繁瑣的then(),和冗長的鏈式調用可讀性變得更長些;
具體使用方式:
//異步函數1
function getData(data){
return new Promise((reslove)=>{
reslove(data)
})
}
//異步函數2
function sayHello(data){
return new Promise((reslove)=>{
reslove(data)
})
}
//異步函數
async function fn(){
// await相當于。then() getData()相當于是回調函數
// await必須在async修飾的函數體內使用
const promiseA = await getData('info')
const promiseB = await sayHello(promiseA);
console.log(promiseB)
}
談談微任務和宏任務
微任務
注意:Promise對象中的代碼是同步的,then()方法中的回調函數才是異步的
then()中的是微任務
宏任務
定時器是宏任務
代碼執行順序口訣:先同步后異步,先微任務后宏任務
總之,同微宏
到此,相信大家對“JavaScript異步怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。