JavaScript異步Promise、Async、await使用舉例詳解
一、JS里的同步異步
fun1(); fun2(); fun3();
如以上代碼,在同步情況下三個函數(shù)應(yīng)該是依次執(zhí)行的,fun1執(zhí)行完執(zhí)行fun2,最終執(zhí)行fun3。
什么是異步呢?異步就是大家各做各的,互不干擾,無需互相等待。
但需注意,各做各的,并不意味著亂序。它依然是順序執(zhí)行的。只不過,fun1沒執(zhí)行完,fun2已經(jīng)開始執(zhí)行了。
JS里的常見異步函數(shù)有:settimeout、fetch、setInterval等。
二、Promise
Promise中文意思是承諾,在JS中,可以通俗理解為:把這個任務(wù)(函數(shù))交給我,我來完成。
1、狀態(tài)
Promise 的三種狀態(tài):pending(等待中)、fulfilled(成功)、rejected(失敗),且狀態(tài)改變是不可逆的。
const p=new Promise((resolve,reject)=>{
resolve("你的成功結(jié)果") //執(zhí)行更改后Promise狀態(tài)變成fulfilled
//reject("失敗的結(jié)果") //執(zhí)行更改后Promise狀態(tài)變成rejected
//throw 1 //拋出異常和reject的效果一樣
})
p.then(res=>res)
//then直接返回會返回包含返回結(jié)果的Promise對象,可以通過.then()繼續(xù)獲取
.then(res=>{
//res對應(yīng)resolve里的值
console.log("fulfilled狀態(tài)時打印")
//以下執(zhí)行可以返回狀態(tài)為rejected的Promise給下一級繼續(xù)執(zhí)行
return new Promise((resolve,reject)=>reject("執(zhí)行出錯"))
}).catch(error=>{
//error對應(yīng)reject里的內(nèi)容
console.log("rejected狀態(tài)時打印")
}).finally(()=>{
console.log("無論成功還是失敗都會打印")
})2、all()、race()、any()
先一句話描述以下Promise.all()、Promise.race()、Promise.any()的區(qū)別:
(1) Promise.all() 中的Promise序列會全部執(zhí)行通過才認(rèn)為是成功,否則認(rèn)為是失?。?/p>
(2) Promise.race() 中Promise序列中第一個執(zhí)行完畢的是通過,則認(rèn)為是成功,如果第一個執(zhí)行完畢的Promise是rejected,則認(rèn)為失敗;
(3) Promise.any() 中Promise序列只有有一個執(zhí)行通過,則認(rèn)為成功,如果全部拒絕,則認(rèn)為失敗。
用一張圖來說明all()、any():

any和all類似,區(qū)別在于any只要有一個成功就返回成功的結(jié)果。
用一張圖來說明race():

Both resolve, but promise2 is faster ,從這里可以看出端倪。顧名思義,Promse.race 就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])里面哪個結(jié)果獲得的快,就返回那個結(jié)果,不管結(jié)果本身是成功狀態(tài)還是失敗狀態(tài)。
3、簡單案例
通過簡單案例了解:
//Promise用法
const param1 = "normal";
const param2 = "error"; // 第二種情況
//1. 創(chuàng)建Promise類的對象
const promise01 = new Promise(function customFun(successFun, failFun) {
if (param1 === "normal") {
successFun("自定義成功的函數(shù)執(zhí)行了!")
} else { //失敗和成功的邏輯都是自定義的
failFun("自定義失敗的函數(shù)執(zhí)行了!")
}
})
const promise02 = new Promise(function customFun(successFun, failFun) { // 第二種情況
if (param2 === "normal") {
successFun("自定義成功的函數(shù)執(zhí)行了!")
} else { //失敗和成功的邏輯都是自定義的
failFun("自定義失敗的函數(shù)執(zhí)行了!")
}
})
//2. 執(zhí)行Promise的返回結(jié)果
promise01.then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
promise02.then(result => { // 第二種情況
console.log(result)
}).catch(error => {
console.log(error)
})可以看到控制臺打印如下:

第一種情況走自定義成功的邏輯,第二種情況走自定義失敗的邏輯。
4、異步執(zhí)行案例
//異步常見案例
const promise03 = new Promise(() => {
console.log("This is Promise constructor.")
setTimeout(() => {
console.log("Timeout executed!")
}, 3000)
})
promise03.then(result => {
console.log(result)
})
console.log("Test Demo.")控制臺輸出:

可以清晰地看到,在Promise被執(zhí)行時,構(gòu)造信息就已經(jīng)打印了,之后,順序執(zhí)行了Test Demo, 等待3秒后系統(tǒng)再執(zhí)行了setTimout里的邏輯。
5、解決異步嵌套繁瑣的場景
//Promise來規(guī)范Timeout嵌套調(diào)用的閱讀性差問題
const promise04 = new Promise((successFun, failFun) => {
setTimeout(() => {
successFun("timeout 333")
}, 3000)
})
const promise05 = promise04.then((res) => {
console.log(res)
return new Promise((successFun, failFun) => {
setTimeout(() => {
successFun("timeout 222")
}, 2000)
})
})
promise05.then(res => {
console.log(res)
})
console.log("Test Demo.")控制臺打印:

可以看到,首先打印了Test Demo,3秒后執(zhí)行了第一各Promise里的內(nèi)容,執(zhí)行完第一個Promise里的內(nèi)容后,再過2秒執(zhí)行了第二各Promise里的內(nèi)容。這比setTimout的多層嵌套,可讀性更好。
三、async和await
async必須用來修飾函數(shù),用來表示該函數(shù)是一個異步函數(shù),await必須和async配套使用。await專門用來修飾Promise的實例化對象。
1、async返回類型
//async有返回類型時,以Promise形式返回
async function asyncDemo01Fun(){
return "Demo01"
}
async function asyncDemo02Fun(){
return Promise.resolve("Demo02")
}
console.log(asyncDemo01Fun())
console.log(asyncDemo02Fun())打印結(jié)果:

可以看到,直接返回結(jié)果和利用Promise.resolve返回結(jié)果是一樣的。
由async修飾的函數(shù),在有返回值時都會直接返回Promise對象,而非直接返回值。
2、async與await結(jié)合使用的簡單案例
//async和await的案例Demo
async function asyncFun1() {
const p = new Promise((successFun, failFun) => {
setTimeout(() => {
successFun({num: 1})
}, 3000)
})
let obj = await p;
console.log(obj)
}
asyncFun1()
console.log("Test Demo.")打印結(jié)果:

可以看到,當(dāng)有await修飾Promise返回對象時,會等待Promise對象執(zhí)行完成后,再返回結(jié)果給對象,最終將獲取到的對象值在3秒后打印。
當(dāng)有await修飾Promise對象時,系統(tǒng)會等待返回值后再返回對象,繼續(xù)執(zhí)行。實際上是將異步處理的事件處理完成后再繼續(xù)執(zhí)行同步代碼。
3、解決異步嵌套問題
//async和await的案例Demo
async function asyncFun2() {
const p1 = new Promise((successFun, failFun) => {
setTimeout(() => {
successFun("Demo 333")
}, 3000)
})
let obj1 = await p1;
console.log(obj1)
const p2 = new Promise((successFun, failFun) => {
setTimeout(() => {
successFun("Demo 222")
}, 2000)
})
let obj2 = await p2;
console.log(obj2)
}
asyncFun2()
console.log("Test Demo.")控制臺打?。?/p>

可以看到,首先打印了Test Demo,3秒后執(zhí)行了第一各Promise里的內(nèi)容,執(zhí)行完第一個Promise里的內(nèi)容后,再過2秒執(zhí)行了第二各Promise里的內(nèi)容。這比setTimout的多層嵌套,可讀性更好。
4、批量請求優(yōu)化
以下是同步獲取請求結(jié)果的案例:
const batchReq=async ()=>{
const url="https://example.com/api/demo"
let rep1=await fetch(`${url}/1/`)
let json1=await rep1.json()
let name1=await json1.data.name
let rep2=await fetch(`${url}/2/`)
let json2=await rep1.json()
let name2=await json1.data.name
let rep3=await fetch(`${url}/3/`)
let json3=await rep1.json()
let name3=await json1.data.name
console.log(name1)
console.log(name2)
console.log(name3)
}以上代碼在執(zhí)行的過程中,由于加了await進(jìn)行修飾,會依次進(jìn)行請求,1執(zhí)行完2執(zhí)行最后3執(zhí)行。
如要實現(xiàn)批量請求同時處理,可以參考以下代碼:
const batchReq = async () => {
try {
const url = "https://example.com/api/demo"
let resp = await Promise.all([fetch(`${url}/1/`), fetch(`${url}/2/`), fetch(`${url}/3/`)])
let jsons = resp.map(res => res.json())
let values = await Promise.all(jsons)
values.map(value => {
console.log(value.data.name)
})
} catch (error) {
console.log(error)
}
}這樣寫便可以批量發(fā)送請求了。
總結(jié)
到此這篇關(guān)于JavaScript異步Promise、Async、await使用的文章就介紹到這了,更多相關(guān)JS異步Promise、Async、await內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解JavaScript Promise和Async/Await
- Javascript的promise,async和await的區(qū)別詳解
- 前端常見面試題之a(chǎn)sync/await和promise的區(qū)別
- 細(xì)數(shù)promise與async/await的使用及區(qū)別說明
- JavaScript Promise與async/await作用詳細(xì)講解
- js中async/await與Promise的區(qū)別
- Node.js 中正確使用 async/await 與 Promise 對象配合(操作方法)
- ES6中Promise、async、await用法超詳細(xì)講解指南
相關(guān)文章
JavaScript實現(xiàn)定時隱藏與顯示圖片的方法
這篇文章主要介紹了JavaScript實現(xiàn)定時隱藏與顯示圖片的方法,可實現(xiàn)javascript定時關(guān)閉圖片的功能,涉及javascript針對頁面元素屬性定時操作的相關(guān)技巧,需要的朋友可以參考下2015-08-08
?JavaScript?數(shù)據(jù)結(jié)構(gòu)之散列表的創(chuàng)建(1)
這篇文章主要介紹了?JavaScript?數(shù)據(jù)結(jié)構(gòu)之散列表的創(chuàng)建,文章圍繞主題相關(guān)內(nèi)容展開詳細(xì)的介紹,需要的小伙伴可以參考一下2022-04-04
前端大文件分片下載具體實現(xiàn)方法(看這一篇就夠了)
本文介紹了在瀏覽器中下載大文件的技術(shù)方案,包括分片下載、斷點續(xù)傳、進(jìn)度條顯示、取消及暫停下載和文件合并等功能,分片下載可以降低網(wǎng)絡(luò)傳輸中斷的風(fēng)險,并減少內(nèi)存占用,需要的朋友可以參考下2024-10-10
js關(guān)閉當(dāng)前頁面(窗口)的幾種方式總結(jié)
js關(guān)閉當(dāng)前頁面(窗口)的幾種方式總結(jié),需要的朋友可以參考一下2013-03-03

