ES6中Promise、async、await用法超詳細(xì)講解指南
Promise
promise狀態(tài)
Promise總是處于以下三種狀態(tài)之一:
pending:初始狀態(tài)fulfilled/resolved:表示成功rejected:表示失敗
狀態(tài)有一些特性:
- 只能通過執(zhí)行函數(shù)修改
- 外部無法讀取
- 外部無法修改
Promise.prototype.then
為
Promise實(shí)例添加處理程序的主要方法,接收的兩個(gè)參數(shù)分別表示進(jìn)入fulfilled/resolved或rejected狀態(tài)時(shí)被調(diào)用,且二者互斥。兩個(gè)參數(shù)可選,但必須是函數(shù)類型,非函數(shù)類型會(huì)被忽略。一個(gè)Promise實(shí)例可以有任意多個(gè)處理程序(任意多個(gè)then調(diào)用)
Promise.prototype.catch
等價(jià)于Promise.prototype.then(null,onRejected)
Promise.prototype.finally
無論狀態(tài)是fulfilled/resolved還是rejected都會(huì)執(zhí)行,但無法得知具體的狀態(tài)(狀態(tài)無關(guān)),一般主要用于清理工作
執(zhí)行次序
示例1
const p = new Promise(resolve => {
console.log('1. excute promise');
setTimeout(() => {
console.log('3. before resolve')
resolve();
console.log('4. after resolve')
}, 100);
})
p.then(() => {
console.log('5. execute resolve')
}).then(()=>{
console.log('6. then2')
}).then(()=>{
console.log('7. then3')
}).finally(()=>{
console.log('8. finally')
});
console.log('2. sync then')
/**
result:
1. excute promise
2. sync then
3. before resolve
4. after resolve
5. execute resolve
6. then2
7. then3
8. finally
*/
示例2
const p = new Promise(resolve => {
setTimeout(() => {
resolve();
}, 100);
})
p.then(()=>{
console.log('then1')
}).then(()=>{
console.log('then2')
}).then(()=>{
console.log('then3')
}).then(()=>{
console.log('then4')
}).then(()=>{
console.log('then5')
});
console.log('async then')
/**
result:
async then
then1
then2
then3
then4
then5
*/
這個(gè)示例中then1、then2、then3、then4、then5相當(dāng)于是同步執(zhí)行的
鏈?zhǔn)秸{(diào)用
then的鏈?zhǔn)秸{(diào)用是Promise最常見的用法,具體方式是每個(gè)執(zhí)行器返回一個(gè)Promise實(shí)例,則后續(xù)每個(gè)then都會(huì)等待前一個(gè)落定后再執(zhí)行,即異步的串行化。以此來解決異步的回調(diào)地獄難題。
es6規(guī)范不支持Promise終止與進(jìn)度查詢,原因是這樣會(huì)使得Promise變得過于復(fù)雜。
鏈?zhǔn)絺髦?/h4>
const p = new Promise(resolve => {
setTimeout(() => {
resolve(100);
}, 100);
})
p.then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return new Promise(resolve => {
setTimeout(() => {
resolve(value + 1)
}, 3000);
});
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
});
/**
100
101
102 等待3秒
103
104
*/
如果執(zhí)行函數(shù)返回的是一個(gè)Promise對(duì)象,則后續(xù)的調(diào)用會(huì)等待該對(duì)象落定后觸發(fā),通過resolve方式傳值;如果不是,則后續(xù)立即觸發(fā),通過return語句向后傳值
const p = new Promise(resolve => {
setTimeout(() => {
resolve(100);
}, 100);
})
p.then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return new Promise(resolve => {
setTimeout(() => {
resolve(value + 1)
}, 3000);
});
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
});
/**
100
101
102 等待3秒
103
104
*/
如果執(zhí)行函數(shù)返回的是一個(gè)Promise對(duì)象,則后續(xù)的調(diào)用會(huì)等待該對(duì)象落定后觸發(fā),通過resolve方式傳值;如果不是,則后續(xù)立即觸發(fā),通過return語句向后傳值
catch對(duì)調(diào)用鏈的影響
catch處在最后
const p = new Promise(resolve => {
setTimeout(() => {
resolve(100);
}, 100);
})
p.then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('fail')
}, 3000);
});
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
}).catch(err => {
console.log('catch', err);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(400)
}, 3000);
});
});
/**
100
101
catch fail
*/
當(dāng)catch處在調(diào)用鏈最后的時(shí)候,則reject后續(xù)的then將不會(huì)被觸發(fā)
catch處在中間
const p = new Promise(resolve => {
setTimeout(() => {
resolve(100);
}, 100);
})
p.then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('fail')
}, 3000);
});
}).then(value => {
console.log(value)
return value + 1;
}).catch(err => {
console.log('catch', err);
return 500;
}).then(value => {
console.log(value)
return value + 1;
}).then(value => {
console.log(value)
return value + 1;
});
/**
100
101
catch fail
*/
catch處在調(diào)用鏈中間,如果返回的不是一個(gè)Promise對(duì)象,后續(xù)的then將不會(huì)被觸發(fā)
async & await
async
語法:
async function name([param[, param[, ... param]]]) {
statements
}
- name:函數(shù)名稱
- param:要傳遞給函數(shù)的參數(shù)的名稱
- statements:包含函數(shù)主體的表達(dá)式,可以使用
await機(jī)制- 返回值:一個(gè)
Promise,這個(gè)Promise要么會(huì)通過一個(gè)由async函數(shù)返回的值被解決,要么會(huì)通過一個(gè)從async函數(shù)中拋出的(或其中沒有被捕獲到的)異常被拒絕
async關(guān)鍵字用于聲明異步函數(shù),可以用在函數(shù)聲明、函數(shù)表達(dá)式、箭頭函數(shù)、方法上:
async function foo() {}
let bar = async function () {}
let baz = async () => {}
class Person{
async say(){}
}
異步函數(shù)如果使用return關(guān)鍵字返回了值,則這個(gè)值會(huì)被Promise.resolve()包裝成一個(gè)Promise對(duì)象:
async function test() {
return 2;
}
test().then(value => {
console.log(value)
})
console.log(1)
/**
1
2
*/
如果函數(shù)體中拋出了異常,可以用catch處理:
async function test() {
const result = 100 / a;
return result;
}
test().catch(value => {
console.log(value)
})
console.log(1)
/**
1
ReferenceError: a is not defined
*/
一些資料中會(huì)說拒絕
Promise的異常不被異步函數(shù)捕獲,但在最新版的Chrome(95.0.4638.69)、Microsoft Edge(95.0.1020.40)、Firefox(93.0)都是支持的:
async function test() {
return Promise.reject('error');
}
test().catch(value => {
console.log(value)
})
console.log(1)
/**
1
error
*/
await
語法:
[返回值] = await 表達(dá)式;
- 表達(dá)式:一個(gè)Promise對(duì)象或者任何要等待的值
- 返回值:返回
Promise對(duì)象的處理結(jié)果。如果等待的不是Promise對(duì)象,則返回該值本身
在用法上,await可以單獨(dú)使用,也可以在表達(dá)式中使用:
async function func(){
console.log(await Promise.resolve('foo'))
}
func();
/**
foo
*/
await只能在async函數(shù)內(nèi)頂層使用,不支持嵌套
在使用多個(gè)
await關(guān)注其結(jié)果,忽視其順序有時(shí)候是個(gè)好事,因?yàn)椴煌囊?guī)范對(duì)于await處理Promise是有差異的。
總結(jié)
到此這篇關(guān)于ES6中Promise、async、await用法超詳細(xì)講解指南的文章就介紹到這了,更多相關(guān)ES6 Promise、async、await內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript事件的綁定基礎(chǔ)實(shí)例講解(34)
這篇文章主要為大家詳細(xì)介紹了javascript事件的綁定基礎(chǔ)實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
JavaScript檢測鼠標(biāo)移動(dòng)方向的方法
這篇文章主要介紹了JavaScript檢測鼠標(biāo)移動(dòng)方向的方法,涉及javascript鼠標(biāo)操作的相關(guān)技巧,需要的朋友可以參考下2015-05-05
JavaScript?數(shù)據(jù)結(jié)構(gòu)之集合創(chuàng)建(1)
這篇文章主要介紹了JavaScript?數(shù)據(jù)結(jié)構(gòu)之集合創(chuàng)建,集合是由一組無序且唯一的元素組成。數(shù)據(jù)結(jié)構(gòu)中的集合,對(duì)應(yīng)的是數(shù)學(xué)概念當(dāng)中的有限集合;下文詳細(xì)介紹需要的小伙伴可以參考一下2022-04-04
前端TypeScript高級(jí)技巧正確做法(讓你的代碼更安全)
TypeScript中豐富的類型系統(tǒng)提供了足夠的靈活性和表達(dá)力,讓用戶可以在保證類型安全的同時(shí)編寫出更加優(yōu)雅和高效的代碼,這篇文章主要介紹了前端TypeScript高級(jí)技巧正確做法的相關(guān)資料,需要的朋友可以參考下2026-04-04
javascript制作網(wǎng)頁圖片上實(shí)現(xiàn)下雨效果
這里給大家分享的是一則使用javascript實(shí)現(xiàn)在網(wǎng)頁圖片上下雨的特效,效果非常炫酷,推薦給小伙伴們。2015-02-02
JavaScript實(shí)現(xiàn)瀏覽器不同標(biāo)簽頁通信的原理與實(shí)踐
這篇文章主要為大家詳細(xì)系統(tǒng)梳理了不同頁簽(Tab / Window / Frame)之間的通信手段以及具體的實(shí)現(xiàn)方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-08-08
JavaScript用select實(shí)現(xiàn)日期控件
這篇文章主要介紹了JavaScript用select實(shí)現(xiàn)日期控件的相關(guān)資料,需要的朋友可以參考下2015-07-07

