Promise是更優雅的實現非同步程式設計的方法(避免了層層巢狀回撥)。
Promise物件有兩種結果狀態:
- resolved:表示非同步操作執行成功了
- rejected:表示非同步操作執行失敗了
狀態只受非同步操作的影響,與其他無關,並且狀態一旦確定則無法改變。
Promise簡單使用:
const promise = new Promise((resolve, reject) => {
let condition = false;
if (condition) {
resolve('promise ok');
} else {
reject(new Error('promise error'));
}
});
promise.then((val) => {
console.log('promise resolve', val);
}, (err) => {
console.log('promise reject', err);
})
// promise reject Error: promise error
複製程式碼
- resolve:在非同步操作成功時(resolved狀態)呼叫
- reject:在非同步操作失敗時(rejected狀態)呼叫
then方法
- 第一個函式引數對應為resolve的執行。
- 第二個函式引數對應為rejecte的執行。
其中回撥中如果有return,則返回的是一個新的promise例項,因此可通過鏈式寫法呼叫新promise例項的then方法。如:
promise.then((val) => {
console.log('promise resolve', val);
return 'val ok';
}).then((val) => {
console.log('promise resolve2', val);
})
// promise resolve promise ok
// promise resolve2 val ok
複製程式碼
catch方法
可用於指定發生錯誤時的回撥函式:
- 當非同步操作結果變為rejected狀態
- then方法指定的回撥函式丟擲錯誤
由於catch可捕獲以上兩種錯誤,因此推薦寫法:
promise.then((val) => {
console.log('promise resolve', val);
}).catch((err) => {
console.log('promise reject', err);
})
// promise reject Error: promise error
複製程式碼
如果catch中丟擲一個錯誤,仍可以被後面的catch方法所捕獲。如:
promise.then((val) => {
console.log('promise resolve', val);
}).catch((err) => {
console.log('catch1 error', err);
throw new Error('catch error');
}).catch((err) => {
console.log('catch2 error:', err);
})
// catch1 error Error: promise error
// catch2 error: Error: catch error
複製程式碼
Promise內如果出現錯誤,但沒有定義錯誤的回撥函式,則不會影響外部的指令碼執行。如:
promise.then((val) => {
console.log('promise resolve', val);
})
console.log('continue');
// continue
複製程式碼
finally方法
不論promise物件最後狀態如何,都會執行此操作。(回撥函式中不接受引數,其本質是then方法的特例)。如:
const promise = new Promise((resolve, reject) => {
resolve();
});
promise.then(() => {
console.log('promise ok');
throw new Error('then error');
}).catch((err) => {
console.log('catch', err);
}).finally(() => {
console.log('finally');
});
// promise ok
// catch Error: then error
// finally
複製程式碼
Promise.all()
接收一個由若干promise物件組成的陣列作為引數。 當所有promise物件的狀態都變成resolved則整體狀態置為resolved,否則整體狀態為rejected。如:
const promise1 = new Promise((resolve, reject) => {
resolve('promise1 ok');
});
const promise2 = new Promise((resolve, reject) => {
throw new Error('promise2 error')
});
Promise.all([promise1, promise2]).then(() => {
console.log('all promises ok');
}).catch((err) => {
console.log('some promise error', err);
});
// some promise error Error: promise2 error
複製程式碼
但當promise2定義了catch去捕獲error時,代表promise2的最終狀態會變為resolved,則promise.all執行then方法的回撥。如:
const promise1 = new Promise((resolve, reject) => {
resolve('promise1 ok');
}).then(() => {
console.log('promise1 ok');
}).catch((err) => {
console.log('promise1 err', err);
});
const promise2 = new Promise((resolve, reject) => {
throw new Error('promise2 error')
}).then(() => {
console.log('promise2 ok');
}).catch((err) => {
console.log('promise2 err', err);
});
Promise.all([promise1, promise2]).then(() => {
console.log('all promises ok');
}).catch((err) => {
console.log('some promise error', err);
});
// promise1 ok
// promise2 err Error: promise2 error
// all promises ok
複製程式碼
Promise.race()
類似於Promise.all(),區別是當第一個promise更新狀態後整體則更新狀態,並且狀態同第一個promise保持一致(與其他promise無關)。如:
const promise1 = new Promise((resolve, reject) => {
resolve('promise1 ok');
});
const promise2 = new Promise((resolve, reject) => {
throw new Error('promise2 error');
});
Promise.race([promise1, promise2]).then(() => {
console.log('first promise ok');
}).catch((err) => {
console.log('first promise error', err);
});
// first promise ok
複製程式碼