new Promise( function(resolve, reject) {...} /* executor */ );
複製代碼
executor
是帶有 resolve
和 reject
兩個參數的函數 。Promise構造函數執行時當即調用executor
函數, resolve
和 reject
兩個函數做爲參數傳遞給executor
(executor 函數在Promise構造函數返回新建對象前被調用)。resolve
和 reject
函數被調用時,分別將promise的狀態改成_fulfilled(完成)或rejected(失敗)。executor 內部一般會執行一些異步操做,一旦完成,能夠調用resolve函數來將promise狀態改爲_fulfilled,或者在發生錯誤時將它的狀態改成rejected。若是在executor函數中拋出一個錯誤,那麼該promise 狀態爲rejected。executor函數的返回值被忽略。
一個 Promise
有如下幾種狀態:javascript
pending: 初始狀態,既不是成功,也不是失敗狀態。html
fulfilled: 意味着操做成功完成。java
rejected: 意味着操做失敗。ajax
let status = 1;
// 判斷status是否爲1,是1的時候執行成功
let p1 = new Promise(function(resolve,reject){
if(status==1){
resolve({msg:"執行成功",status:"200"}); // 這裏傳遞給resolve的數據就是以後then中接受到的res
}else{
reject({msg:"執行失敗",status:"404"}); // 對應catch中的err
}
});
p1.then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
複製代碼
promise能夠當作是去肯德基買漢堡,先預約一個漢堡,而後收營員會給你一小票並向你承諾以後會給你一個漢堡(也可能漢堡買完了沒有漢堡)。從下單到得到漢堡的這個過程能夠當作是異步的操做,期間你能夠刷一下子手機,同時後廚在準備漢堡。有了漢堡以後吃漢堡(處理resolve),或者沒有漢堡了發生退款(處理reject)。
你在等待這個承諾的到來,一旦到來你就能夠開始吃漢堡或者沒有漢堡遺憾的退款。數組
then
並非處理promise
實例返回的resolve
狀態值,resolve
和reject
狀態的值都可以處理,第一個回調函數處理成功,第二個回調函數處理失敗,若是缺省第二個處理失敗的回調,則狀態爲reject
的promise
傳遞到下一個鏈式調用。 promise
只有兩種變化過程,並且變化以後以後不會發生變化,會保持狀態的一致
只能從 _pending -> fulfilled 或者 從 pending -> rejected _一旦狀態發生變化就不會再發生改變,保持一致性。(你去買漢堡只可能有兩種狀態,買到漢堡和沒有買到,並且不可能在二者之間變化)異步
var promise = new Promise((resolve, reject) => {
// 只能改變一次狀態
resolve('1') // 改變狀態
resolve('2') // 不生效
resolve('3') // 不生效
console.log('4') //同步執行
})
// 屢次調用promise中的值不會發生變化
promise.then((data) => {
console.log('第一個then', data)
})
promise.then((data) => {
console.log('第二個then', data)
})
// 4
// 第一個then 1
// 第二個then 1
複製代碼
promise
能夠鏈式調用不是由於使用return this
, 而是在then
和 catch
以後返回了一個promise
then
或者catch
返回當即值,則返回的promise
是resolved
狀態,至關於Promise.resolve(..)
Promise.reject(..)
,則返回的promise
是rejected
狀態var promise = new Promise((resolve, reject) => {
resolve('1')
})
promise.then((data) => {
console.log(data) // 1
return 2 // 做爲新的promise的resolve值返回
}).then((data) => {
// 這裏接收的是上一個then返回的新的promise的resolve狀態
console.log(data) // 2
})
promise.then((data) => {
// 能夠返回一個promise
return Promise.reject('錯誤')
}).catch((data) => {
// catch接收上一個then返回的promise
console.log(data) // 錯誤, 接收上一個鏈上的promise的resolve返回
}).then((data) => {
console.log(data) // undefined 前一個鏈上的promise沒有返回值
})
promise.then((data)=>{
// 拋出錯誤
throw new Error('出錯')
}).catch((err) => {
// 上一個promise返回的是reject, 內容是 拋出的error
console.log(err)
})
// 1
// 2
// Error: 出錯
// at promise.then (3.html:32)
// 錯誤
// undefined
複製代碼
return new Error('錯誤')
的方式返回異常不能被下一個catch
捕獲到,這裏返回的promise
是resolve
狀態,會被傳遞下去被then
捕獲,只有throw new Error()
才能被下一個catch
捕獲var promise = new Promise((resolve, reject) => {
resolve('1')
})
promise.then((data) => {
return new Error('錯誤')
}).catch((err) => {
console.log('不會執行')
}).then((data) => {
console.log('打印以前返回的錯誤', data)
})
// 打印以前返回的錯誤 Error: 錯誤
// at promise.then (4.html:16)
複製代碼
then(success, error)
then
能夠由兩個處理函數,第一個用來處理resolved
狀態的promise
返回值,第二個用來處理rejected
狀態的promise
返回值,這裏處理的是鏈式調用的返回的前一個promise
var promise = new Promise((resolve, reject) => {
reject('錯誤')
})
promise.then((data)=>{
console.log('不會執行,promise狀態是rejected')
}, (err)=>{
// 捕獲到錯誤
console.log(err) // 錯誤
}).catch((err) => {
// 鏈式調用的前一個promise返回是一個resolve狀態
console.log('不能捕獲到錯誤')
})
複製代碼
then
中沒有指定處理rejected
狀態的函數時,錯誤狀態會一直傳遞下去直到被處理,要是沒有處理不會被window
捕獲,直接控制檯報錯...window.addEventListener('error', (e) => {
console.log(e)
})
var promise = new Promise((resolve, reject) => {
reject('錯誤')
})
promise.then((data)=>{
console.log('未對錯誤處理')
}).catch((err) => {
// 執行
console.log('上一個then中缺省處理錯誤的函數,錯誤會被封裝成新的promise向下傳遞', err)
})
promise.then((data)=>{
console.log('不處理,也沒有後續,錯誤會被window捕捉到')
})
複製代碼
.then
的第二個處理錯誤的函數捕獲不了第一個處理成功的函數拋出的錯誤,然後續的 .catch
能夠捕獲以前的錯誤var promise = new Promise((resolve, rejected) => {
resolve(1)
})
promise.then((data)=>{
throw new Error('2')
}, (err) => {
console.log('不能捕獲,then中第一個成功回調返回的錯誤')
}).catch((err)=>{
console.log('能夠捕獲上一個then中成功或者錯誤處理函數中拋出的錯誤')
})
複製代碼
// 傳入當即數
Promise.resolve(1).then((data)=>{console.log(data)}) // 1
// 傳入promise對象
var p1 = new Promise((resolve,reject) => {
resolve(2)
})
var p2 = Promise.resolve(p1)
console.log(p1 === p2) // true 返回同一個
// thenable
var o = {
then:function(cb,err){
console.log('then函數')
cb(3)
}
}
Promise.resolve(o).then((data)=>{console.log(data)}) // then函數 3
複製代碼
判斷一個函數是否是thenable函數
if(!!p
&&
(typeof p === 'object' || typeof p === 'function')
&&
(p.then && typeof p.then === 'function')
) { console.log(true)} else {
console.log('false)
}
複製代碼
Promise.all
方法常被用於處理多個promise
對象的狀態集合。輸入是一個由promise
對象組成的數組,全部的promise對象都成功的時候纔會觸發成功,一旦有任何一個iterable
裏面的promise
對象失敗則當即觸發該promise
對象的失敗。這個新的promise
對象在觸發成功狀態之後,會把一個包含iterable
裏全部promise
返回值的數組做爲成功回調的返回值,順序跟iterable
的順序保持一致;若是這個新的promise
對象觸發了失敗狀態,它會把iterable
裏第一個觸發失敗的promise
對象的錯誤信息做爲它的失敗錯誤信息。ui
這時候能夠這樣,將一組ajax請求封裝成一組promise
對象傳入Promise.all
,返回結果也是有序的,再對這個有序的promise
對象進行處理this
Promise.race
當iterable
參數裏的任意一個子promise
被成功或失敗後,父promise
立刻也會用子promise
的成功返回值或失敗詳情做爲參數調用父promise
綁定的相應句柄,並返回該promise
對象。(任意一個成功或者失敗就觸發)
此時能夠構造一個 定時器任務和一個ajax
請求,封裝成promise
對象傳入Promise.race
,若是定時器的結果先返回,則請求超時