目錄
異步和同步
異步的問題
new Promise語法
promise的狀態
promise.then()
Promise.resolve()
Promise.reject()
Promise.all()
Promise.race()
Promise.catch()
Promise.finally()
異步和同步
同步模式下,代碼按順序執行,前一條執行完畢后,進行后一條的執行。
異步模式下,代碼可以不按順序執行,不同行的代碼可以同時執行。
異步的問題
有時,一條代碼需要一個異步操作的返回值才能進行計算,這就會導致回調問題,promise語法可以優雅地解決回調。
new Promise語法
new Promise用于創建Promise實例,其參數是一個函數。
const demo = new Promise( ( resolve, reject )=>{if(){...resolve(); }if(){...reject();}}
)
作為參數的函數接收兩個參數。為resolve和reject(參數名可以修改,但一般都用resolve和reject),resolve和reject也為函數。
promise的狀態
promise實例具有三個狀態:成功(fulfilled,但有時也叫resolved)、失敗、待定。
當調用resolve()函數時,promise的狀態會變成成功。
當調用reject()函數時,promise的狀態會變為失敗。
當promise的狀態為成功或失敗時,會進入Promise.then()。
在new Promise中,若調用throw,會觸發reject狀態。
let a = new Promise((resolve,reject)=>{throw Error('error!');});console.log(a);
promise.then()
接收兩個參數,第一個參數是promise狀態變為成功時,執行的函數,第二個參數是promise狀態為失敗時調用的函數。
demo.then(()=>{//如果resolve被觸發,執行的函數},()=>{//如果reject被觸發,執行的函數}
)
傳參
在new Promise參數函數中,reject和resolve可以傳遞參數,在.then對應的處理函數中,可以獲得這個參數,且兩個參數的名稱不需要對應。
const demo = new Promise( ( resolve, reject )=>{if(){...resolve(num1); }if(){...reject(num2);}}).then((resolveData)=>{...},(rejectData)=>{})
.then中的參數名resolveData和rejectData是可以修改的,這里只是隨便起的名字,不是一定要叫這個。
Promise.resolve()
Promise.resolve()方法返回一個Promise對象。
Promise.resolve的參數為非Promise參數時,其返回的Promise對象狀態為成功,值為傳入的參數。
若Promise.resolve的參數為Promise參數,其返回的Promise對象的狀態與值,取決于參數Promise。
let a = Promise.resolve(1);let b = Promise.resolve(function(){return 1+1;});let c = Promise.resolve(new Promise((resolve,reject)=>{reject();}));console.log(a);console.log(b);console.log(c);
Promise.reject()
與Promise.resolve()類似。
但與resolve不同的是,不管傳入的參數如何,返回的Promise狀態都是失敗。
傳入的參數是什么,該參數的返回值會成為返回的Promise的值。
即使傳入的參數是成功的Promise對象,返回值也是失敗的Promise。
let a = Promise.reject(new Promise((resolve,reject)=>{resolve("resolve!!!");}));console.log(a);
當傳入的參數是成功的Promise,這個Promise會作為失敗Promise的值。但返回的Promise狀態仍然是失敗。
當傳入的參數是失敗的Promise,整個失敗的Promise會作為返回的Promise的值。
let a = Promise.reject(new Promise((resolve,reject)=>{reject("reject!!!");}));console.log(a);
Promise.all()
Promise.all()方法接收一個數組。
該數組一般情況下,其中每一個元素都是Promise。
其返回的結果也是Promise,只有當數組中所有的Promise都成功時,才返回成功,成功的結果是每個Promise對象成功結果組成的一個數組,否則返回失敗,失敗的結果是第一個失敗的Promise的結果。
Promise全成功的情況下:
若傳入的參數不是Promise,則該參數會被視為成功值。
let p1 = Promise.resolve(1);let p2 = 2;let p3 = Promise.resolve(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let a = Promise.all([p1,p2,p3,p4]);console.log(a);
有失敗Promise的情況下:
let p1 = Promise.resolve(1);let p2 = 2;let p3 = Promise.reject(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let p5 = new Promise((resolve,reject)=>{reject('reject');})let a = Promise.all([p1,p2,p3,p4,p5]);console.log(a);
Promise.race()
Promise.race()方法接收一個數組。
該數組一般也都由Promise組成。返回值為第一個改變狀態的Promise。
當數組元素為非Promise結構時,該非Promise結構會被視為成功的Promise并返回。
let p1 = Promise.resolve(1);let p2 = null;let p3 = Promise.reject(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let p5 = new Promise((resolve,reject)=>{reject('reject');})let a = Promise.race([p2,p1]);
Promise.catch()
Promise.catch()的語法有點像語法糖。
Promise.catch(reject)從語法上講,相當于promise.then(null, reject),這里的reject都是指處理reject狀態的回調函數。
.catch返回值也是一個Promise。
Promise.finally()
Promise.finally()方法,不論Promise的狀態是成功還是失敗,在最后都會調用finally中的方法。
finally可以用于處理不論返回結果如何,都需要執行的邏輯,可以避免代碼冗余。
finally接收的是一個函數。
finally的返回值是一個新的Promise實例對象。
該對象的狀態一般是父Promise狀態的傳遞。父Promise是指promise.finally中,promise對應的實例。但當finally的返回值是顯式reject或pending Promise時,返回值是reject或pending。
下例中,pTest的返回值是一個狀態為失敗的Promise,調用pTest時,雖然finally參數的返回值是成功的promise,但是由于該promise的狀態不是失敗或待定,所以finally的返回值取決于父Promise,即pTest。
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{resolve('ok');})}));
但若finally參數返回的是reject或者pending,則返回值取決于參數。
參數返回reject的情況下:
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{reject('reject');})}));
參數返回panding的情況下:
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{})}));