ES6中Promise、async、await用法超詳細(xì)講解指南
Promise
promise狀態(tài)
Promise
總是處于以下三種狀態(tài)之一:
pending
:初始狀態(tài)fulfilled/resolved
:表示成功rejected
:表示失敗
狀態(tài)有一些特性:
- 只能通過(guò)執(zhí)行函數(shù)修改
- 外部無(wú)法讀取
- 外部無(wú)法修改
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
無(wú)論狀態(tài)是fulfilled/resolved
還是rejected
都會(huì)執(zhí)行,但無(wú)法得知具體的狀態(tài)(狀態(tài)無(wú)關(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
最常見(jiàn)的用法,具體方式是每個(gè)執(zhí)行器返回一個(gè)Promise
實(shí)例,則后續(xù)每個(gè)then
都會(huì)等待前一個(gè)落定后再執(zhí)行,即異步的串行化。以此來(lái)解決異步的回調(diào)地獄難題。
es6
規(guī)范不支持Promise
終止與進(jìn)度查詢,原因是這樣會(huì)使得Promise
變得過(guò)于復(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ā),通過(guò)resolve
方式傳值;如果不是,則后續(xù)立即觸發(fā),通過(guò)return
語(yǔ)句向后傳值
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ā),通過(guò)resolve
方式傳值;如果不是,則后續(xù)立即觸發(fā),通過(guò)return
語(yǔ)句向后傳值
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
語(yǔ)法:
async function name([param[, param[, ... param]]]) { statements }
- name:函數(shù)名稱
- param:要傳遞給函數(shù)的參數(shù)的名稱
- statements:包含函數(shù)主體的表達(dá)式,可以使用
await
機(jī)制- 返回值:一個(gè)
Promise
,這個(gè)Promise
要么會(huì)通過(guò)一個(gè)由async
函數(shù)返回的值被解決,要么會(huì)通過(guò)一個(gè)從async
函數(shù)中拋出的(或其中沒(méi)有被捕獲到的)異常被拒絕
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ì)說(shuō)拒絕
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
語(yǔ)法:
[返回值] = 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 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)
這篇文章主要介紹了JavaScript 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)別介紹,需要的朋友可以參考下2018-03-03JavaScript 大數(shù)據(jù)相加的問(wèn)題
寫一個(gè)函數(shù)處理大數(shù)據(jù)的相加問(wèn)題,所謂的大數(shù)據(jù)是指超出了整型,長(zhǎng)整型之類的常規(guī)數(shù)據(jù)類型表示范圍的數(shù)據(jù)。實(shí)現(xiàn)語(yǔ)言不限。2011-08-08javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)
這篇文章主要介紹了javascript面向?qū)ο髣?chuàng)建對(duì)象的方式,結(jié)合實(shí)例形式總結(jié)分析了javascript常見(jiàn)的7種創(chuàng)建對(duì)象的方式,需要的朋友可以參考下2019-07-07詳解如何使用微信小程序云函數(shù)發(fā)送短信驗(yàn)證碼
這篇文章主要介紹了詳解如何使用微信小程序云函數(shù)發(fā)送短信驗(yàn)證碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03JS實(shí)現(xiàn)title標(biāo)題欄文字不間斷滾動(dòng)顯示效果
這篇文章主要介紹了JS實(shí)現(xiàn)title標(biāo)題欄文字不間斷滾動(dòng)顯示效果,通過(guò)javascript時(shí)間函數(shù)定時(shí)操作動(dòng)態(tài)修改頁(yè)面元素實(shí)現(xiàn)滾動(dòng)效果,需要的朋友可以參考下2016-09-09