Promise 的定義
Pormise是JS的非同步程式設計的一種解決方案,在ES6將其寫進了語言標準,提供了原生的Promise物件。
Promise簡單來理解就是一個容器,裡面存放著某個未來才會結束的事件結果。Promise是一個物件,從它可以獲取非同步操作的訊息,Promise提供了統一的API,各種非同步操作都可以用同樣的方法進行處理。
Promise有下面兩個特點:
物件的狀態不受外界影響。有三種狀態:padding(進行中)、fulfilled(成功)、rejected(失敗)。只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
一旦狀態改變,就不會再變,任何時候都可以得到這個結果。三個狀態只有從padding到fulfilled或者從padding到rejected。狀態只有從padding改變到fulfilled或者refected,兩種改變。
有了Promise物件,就可以將非同步操作以同步操作的流程表達出來,避免了層層巢狀的回撥函式。此外,Promise物件提供統一的介面,使得控制非同步操作更加容易。
Promise存在的缺點
無法取消Promise,一旦新建它就會立即執行,無法中途取消。
如果不設定回撥函式,Promise內部丟擲的錯誤,不會反應到外部。
當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
Promise基本用法
const promise = new Promise((resolve, reject) => {
let status = true;
if (status) {
resolve('操作成功!');
} else {
reject('操作失敗!');
}
});
promise.then(res => {
console.log('成功結果:' + res);
}, error => {
console.log('失敗結果:' + error);
});
複製程式碼
ES6中,Promise物件是一個建構函式,用來生成Promise例項。Promise建構函式接受一個函式作為引數,接受兩個引數,分別是resolve和reject兩個函式。
其中,resolve函式作用是將Promise的狀態從padding改變成fufilled;而reject函式作用是將Promise的狀態從padding改變成rejected。
在Promise例項生產後,可以用then方法分別指定了fufilled狀態和rejected狀態的回撥函式。
其中then方法接受兩個引數,第一個回撥函式是狀態改變fufilled時呼叫的,第二個回撥函式是狀態改變refected時呼叫的。第二個引數是可選的,不一定要提供。
const promise = new Promise((resolve, reject) => {
console.log('new Promise()');
resolve();
});
promise.then(() => {
console.log('resolve()');
});
console.log('End');
複製程式碼
上面是一個Promise對的簡單寫法,我們看下上面的例子是如何輸出的。
// 執行結果
new Promise()
End
resolve()
複製程式碼
在上面的例子中因為Promise物件是同步的所以先輸出,then方法是非同步的所以後輸出。
Promise的語法糖then
Promise例項具有then方法,then方法是定義在原型物件Promise.prototype上的。它的作用前面說過,第一個回撥函式是狀態改變fufilled時呼叫的,第二個回撥函式(可選)是狀態改變rejected時呼叫的。
new Promise((resolve, reject) => {
resolve('王小端Coder');
}).then(res => {
console.log(res); // 王小端Coder
});
複製程式碼
then方法的基礎呼叫寫法,可以寫一個回撥方法,來執行成功後的回撥。then方法返回一個的是一個新的Promise例項,因此我們可以採用鏈式寫法,即then方法後面再呼叫一個then方法。
new Promise((resolve, reject) => {
resolve('王小端Coder');
}).then(res => res).then(res => {
console.log(res); // 王小端Coder
});
複製程式碼
採用鏈式的then,可以指定一組按照次序呼叫的回撥函式。這時,前一個回撥函式,有可能返回的還是一個Promise物件(即有非同步操作),這時後一個回撥函式,就會等待該Promise物件的狀態發生變化,才會被呼叫。
Promise的語法糖catch
catch是用於指定發生錯誤的回撥函式。
new Promise((resolve, reject) => {
reject('失敗');
}).catch(error => {
console.log(error); // 失敗
});
複製程式碼
Promise例項當狀態改變為rejected狀態或者操作失敗丟擲異常錯誤,就會被catch方法捕獲。所以在Promise例項中reject方法等同於丟擲錯誤。如果Promise的狀態已經變成了resolved,再丟擲錯誤無效。
new Promise((resolve, reject) => {
reject('失敗');
throw new Error('丟擲異常'); // 這行無效
}).catch(error => {
console.log(error); // 失敗
});
複製程式碼
Promise的finally方法
finally方法用於指定不管Promis物件最後狀態如何,都會執行的操作。該方法是 ES2018 引入標準的。
new Promise((resolve, reject) => {
resolve();
}).then(res => {
console.log('success');
}).catch(error => {
console.log('error');
}).finally(() =>{
console.log('finally');
})
複製程式碼
Promise的all方法
Promise.all方法用於將多個Promise例項,包裝成一個新的Promise例項。在all方法中可以傳遞多個Promise物件,當所有的Promise物件狀態都返回fufilled,才會返回fulfilled,否則返回rejected。
const promise1 = new Promise((resolve, reject) => {
resolve();
})
const promise2 = new Promise((resolve, reject) => {
resolve();
})
const promise3 = new Promise((resolve, reject) => {
resolve();
})
const promiseAll = Promise.all([promise1, promise2, promise3]).then(res => {
console.log('all');
})
複製程式碼
Promise的race方法
Promise.race方法同樣是將多個Promise例項,包裝成一個新的Promise例項。可以傳遞多個Promise物件作為引數,如果例項紅有一個例項率先改變狀態,那麼race的狀態就會跟著改變。
const promise1 = new Promise((resolve, reject) => {
reject();
})
const promise2 = new Promise((resolve, reject) => {
resolve();
})
const promise3 = new Promise((resolve, reject) => {
reject();
})
const promiseRace = Promise.race([promise1, promise2, promise3]).then(res => {
console.log('race then');
}).catch(error => {
console.log('race catch');
})
複製程式碼
Promise 結束!謝謝大家能夠指出其中的不足。