雖然回調(diào)函數(shù)是所有異步編程方案的根基驶悟;但是如果我們直接使用傳統(tǒng)回調(diào)方式去完成復(fù)雜的異步流程疆虚,就會(huì)無(wú)法避免大量的回調(diào)函數(shù)嵌套仁连;導(dǎo)致回調(diào)地獄的問(wèn)題。
為了避免這個(gè)問(wèn)題滑频。CommonJS社區(qū)提出了Promise的規(guī)范捡偏,ES6中稱為語(yǔ)言規(guī)范。
MDN:Promise
Promise 對(duì)象用于表示一個(gè)異步操作的最終完成 (或失敗)及其結(jié)果值峡迷。
一個(gè) Promise 必然處于以下幾種狀態(tài)之一:
待定(pending): 初始狀態(tài)银伟,既沒(méi)有被兌現(xiàn),也沒(méi)有被拒絕绘搞。
已兌現(xiàn)(fulfilled): 意味著操作成功完成彤避。
已拒絕(rejected): 意味著操作失敗。
基本用法
已兌現(xiàn)(fulfilled):
const promise = new Promise((resolve, reject) => {
resolve(1)
})
promise.then((value) => {
console.log('resolved', value) // resolve 1
},(error) => {
console.log('rejected', error)
})
已拒絕(rejected):
const promise = new Promise((resolve, reject) => {
reject('失敗了')
})
promise.then((value) => {
console.log('resolved', value)
},(error) => {
console.log('rejected', error) // rejected 失敗了
})
即便promise中沒(méi)有任何的異步操作夯辖,then方法的回調(diào)函數(shù)仍然會(huì)進(jìn)入到事件隊(duì)列中排隊(duì)琉预。
Promise的本質(zhì)上也是使用回調(diào)函數(shù)的方式去定義異步任務(wù)結(jié)束后所需要執(zhí)行的任務(wù)。這里的回調(diào)函數(shù)是通過(guò)then方法傳遞過(guò)去的
鏈?zhǔn)秸{(diào)用
- promise對(duì)象then方法蒿褂,返回了全新的promise對(duì)象圆米∽湓荩可以再繼續(xù)調(diào)用then方法,如果return的不是promise對(duì)象娄帖,而是一個(gè)值也祠,那么這個(gè)值會(huì)作為resolve的值傳遞,如果沒(méi)有值近速,默認(rèn)是undefined
- 后面的then方法就是在為上一個(gè)then返回的Promise注冊(cè)回調(diào)
- 前面then方法中回調(diào)函數(shù)的返回值會(huì)作為后面then方法回調(diào)的參數(shù)
- 如果回調(diào)中返回的是Promise诈嘿,那后面then方法的回調(diào)會(huì)等待它的結(jié)束
異常處理
- then的第二個(gè)參數(shù)onRejected方法
- catch()
兩者的區(qū)別:
catch是給整個(gè)promise鏈條注冊(cè)的一個(gè)失敗回調(diào);
而then的第二個(gè)參數(shù)onRejected方法削葱,只能捕獲第一個(gè)promise的報(bào)錯(cuò)奖亚,如果當(dāng)前then的resolve函數(shù)處理中有報(bào)錯(cuò)是捕獲不到的。
使用.catch方法更為常見(jiàn)析砸,因?yàn)楦臃湘準(zhǔn)秸{(diào)用
ajax('/api/user.json')
.then(function onFulfilled(res) {
console.log('onFulfilled', res)
}).catch(function onRejected(error) {
console.log('onRejected', error)
})
等價(jià)于
ajax('/api/user.json')
.then(function onFulfilled(res) {
console.log('onFulfilled', res)
})
.then(undefined, function onRejected(error) {
console.log('onRejected', error)
})
常用的靜態(tài)方法
- Promise.resolve()
- Promise.reject()
- Promise.all()
- Promise.race()
Promise案例
function ajax (url) {
return new Promise((resolve, rejects) => {
// 創(chuàng)建一個(gè)XMLHttpRequest對(duì)象去發(fā)送一個(gè)請(qǐng)求
const xhr = new XMLHttpRequest()
// 先設(shè)置一下xhr對(duì)象的請(qǐng)求方式是GET昔字,請(qǐng)求的地址就是參數(shù)傳遞的url
xhr.open('GET', url)
// 設(shè)置返回的類型是json,是HTML5的新特性
// 我們?cè)谡?qǐng)求之后拿到的是json對(duì)象干厚,而不是字符串
xhr.responseType = 'json'
// html5中提供的新事件,請(qǐng)求完成之后(readyState為4)才會(huì)執(zhí)行
xhr.onload = () => {
if(this.status === 200) {
// 請(qǐng)求成功將請(qǐng)求結(jié)果返回
resolve(this.response)
} else {
// 請(qǐng)求失敗李滴,創(chuàng)建一個(gè)錯(cuò)誤對(duì)象,返回錯(cuò)誤文本
rejects(new Error(this.statusText))
}
}
// 開(kāi)始執(zhí)行異步請(qǐng)求
xhr.send()
})
}
ajax('/api/user.json').then((res) => {
console.log(res)
}, (error) => {
console.log(error)
})
======================分割線======================
關(guān)于Promise源碼分析可以看另外一篇:Promise手寫(xiě)