概述
回調(diào)函數(shù)是JavaScript異步編程的根基,但如果我們直接使用傳統(tǒng)回調(diào)方式去完成復(fù)雜的異步流程,就無(wú)法避免回調(diào)函數(shù)嵌套的問(wèn)題,即常說(shuō)的“回調(diào)地獄”。
為了解決這個(gè)問(wèn)題,CommonJS社區(qū)提出了Promise規(guī)范,在ES2015中被標(biāo)準(zhǔn)化,成為語(yǔ)言規(guī)范。
Promise就是一個(gè)對(duì)象,用來(lái)表示一個(gè)異步任務(wù)在最終結(jié)束后,是成功還是失敗。類似于內(nèi)部對(duì)外界做出了一個(gè)“承諾”,一開始,處于待定狀態(tài)(Pending),最終有可能是成功(Fulfilled)狀態(tài),也有可能是失?。?code>Rejected)狀態(tài),最終的結(jié)果狀態(tài)明確后,都會(huì)有相應(yīng)的任務(wù)被執(zhí)行,一但結(jié)果明確,就不可能再發(fā)生改變。
快速上手
const promise = new Promise(function (resolve, reject) {
// 這里用于兌現(xiàn)承諾
// 這里的代碼會(huì)被同步執(zhí)行,屬于同步任務(wù)
console.log(1)
resolve(100) // 承諾達(dá)成
//reject(new Error('promise rejected')) // 承諾失敗
})
// then 方法接收兩個(gè)參數(shù),第一個(gè)是成功回調(diào),第二個(gè)是失敗回調(diào)
promise.then(function(value) {
// promise的回調(diào)屬于微任務(wù)
console.log('resolved', value)
}, function (error) {
console.log('rejected', error)
})
如果在回調(diào)函數(shù)中又需要發(fā)起一次異步任務(wù),循環(huán)往復(fù),依然會(huì)出現(xiàn)“回調(diào)地獄”,這是使用Promise的一個(gè)常見誤區(qū),對(duì)于這種情況,我們應(yīng)該借助于Promise then方法鏈?zhǔn)秸{(diào)用的特點(diǎn),保證異步任務(wù)的扁平化。
鏈?zhǔn)秸{(diào)用
-
then方法內(nèi)部會(huì)返回一個(gè)全新的Promise對(duì)象 - 后面的
then方法就是在為上一個(gè)then返回的Promise注冊(cè)回調(diào) - 前面
then方法中回調(diào)函數(shù)的返回值會(huì)作為后面then方法回調(diào)的參數(shù) - 如果回調(diào)中返回的是
Promise,那后面then方法的回調(diào)會(huì)等待它的結(jié)束 - 使用
catch捕獲異??梢圆东@到Promise鏈條上的異常,但上一個(gè)示例中的第二個(gè)參數(shù)捕獲異常函數(shù)只是給第一個(gè)Promise注冊(cè)了失敗回調(diào)
const promise = new Promise(function (resolve, reject) {
resolve(100)
})
promise.then(function(value) {
console.log('resolved', value)
}).then(function (value){
console.log(value) // undefined
throw new Error()
}).catch(function (error) {
// catch 方法捕獲異常
console.log('error') // 'error'
})
靜態(tài)方法
resolve
- 該方法的作用是,快速的把一個(gè)值轉(zhuǎn)換成一個(gè)
Promise對(duì)象,例如Promise.resolve('foo')Promise.resolve('foo').then(value => { console.log(value) // 'foo' }) - 如果resolve的參數(shù)是一個(gè)promise,則會(huì)原樣返回這個(gè)promise
let promise = new Promise((resolve, reject) => {}) let promise2 = Promise.resolve(promise) console.log(promise === promise2) // true
reject
- 與
resolve類似,會(huì)快速創(chuàng)建一個(gè)狀態(tài)為失敗的Promise對(duì)象
all
- 參數(shù)為一個(gè)數(shù)組,當(dāng)內(nèi)部所有
Promise都執(zhí)行完畢后,返回的Promise狀態(tài)才會(huì)改變,若有一個(gè)Promise狀態(tài)為失敗,則返回的Promise對(duì)象狀態(tài)也會(huì)變成失敗,不再等待其它的Promise
let p1 = new Promise((resolve, reject) => {
resolve('p1')
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function () {
resolve('p2')
}, 1000)
})
let p3 = new Promise((resolve, reject) => {
resolve('p3')
})
Promise.all([p1, p2, p3]).then(res => {
// 返回的結(jié)果與參數(shù)Promise對(duì)應(yīng)
console.log(res) // ["p1", "p2", "p3"]
}).catch(error => {
console.log(error)
})
race
all方法是等待所有任務(wù)結(jié)束,而race只會(huì)等待第一個(gè)結(jié)束的任務(wù)