(JS基礎)Promise 對象

概述

Promise對象是一個代理對象(代理一個值),被代理的值在Promise對象建立時多是未知的javascript

Promise對象有三種狀態pending(初始狀態)、fulfilled(成功狀態)、rejected(失敗狀態)。java

Promise對象的狀態一旦由pending變爲fulfilledrejected沒法再更改promise

Promise對象的狀態變爲fulfilled後,經過then()方法執行回調函數;狀態變爲rejected後,經過catch()方法執行回調函數。dom

在 ES2018 中引入了finally(),表示該Promise執行結束後(不管是"then"仍是"catch"致使的結束)都會執行傳入finally方法的回調函數,回調函數無參數。異步


簡單示例

建立

經過new運算符能夠建立Promise實例,惟一參數是帶有 resolvereject兩個參數的 executor函數resolvereject函數被調用時,分別將Promise的狀態改成fulfilled(完成)或rejected(失敗),兩個函數都接受一個參數,做爲成功(或失敗)的信息傳遞給對應的處理方法(thencatch)。函數

let p = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (Math.random() > 0.5) {
      resolve('resolve');
    } else {
      reject('reject');
    }
  }, 1000);
});複製代碼

上述例子中,1 秒後隨機把Promise對象的狀態改成fulfilled(完成)或rejected(失敗)。ui

處理

被建立的Promise對象會當即執行executor函數,若是咱們還須要在該異步函數結束後再作點什麼,就須要調用Promise對象的then()catch()finally()方法。(三個方法都會返回一個新的Promise對象,所以能使用"鏈式操做")spa

接上例子:prototype

p.then(res => {
  console.log(res);   // 'resolve'
}).catch(err => {
  console.log(err);   // 'reject'
}).finally(()=>{
  console.log('finally');    // 一定執行
});複製代碼

能夠看出,then()catch()方法傳入的是一個回調函數,該回調函數有惟一參數,對應的是resolvereject函數傳入的參數。finally()一樣是傳入一個對調函數,不一樣的是該回調函數無參數。代理

幾種場景

場景1:多個Promise須要依次執行。(Promise.prototype.then()能夠傳入另外一個Promise對象

const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1成功執行後再執行promise2,再是promise3
promise1.then(promise2).then(promise3);複製代碼

場景2:多個Promise須要都成功。(靜態方法:Promise.all()

const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1/2/3 均成功後再執行 then ( 其中一個失敗也不會執行 then )
Promise.all([promise1, promise2, promise3]).then(callback(){...});複製代碼

場景3:多個Promise只須要其中一個成功。(靜態方法:Promise.race()

const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1/2/3 任意一個成功後執行 then
Promise.race([promise1, promise2, promise3]).then(callback(){...})
複製代碼

Promise.resolve()

Promise.resolve()用於生成一個狀態爲fulfilledPromise對象。其參數與.prototype.resolve()一致。

let p1 = Promise.resolve('resolve');
// 等效以下代碼
let p2 = new Promise((resolve, reject) => {
  resolve('resolve');
});複製代碼

Promise.reject()

Promise.reject()用於生成一個狀態爲rejectedPromise對象。其參數與.prototype.reject()一致。

let p1 = Promise.reject('resolve');
// 等效以下代碼
let p2 = new Promise((resolve, reject) => {
  reject('resolve');
});複製代碼


繼續深刻了解

then() 的第二個參數

其實上面的介紹中,徹底沒有說起then()的第二個參數,由於其做用與catch()方法一致。看下面例子:

let p = new Promise((resolve, reject) => {
  reject('reject');
})
p.then(res => { }, err => {
  console.log(err);     // 'reject'
});
p.catch(err => {
  console.log(err);     // 'reject'
});
複製代碼

不傳參的 then()/catch()/finally()

then()/catch()/finally()不傳入參數,都會返回與原Promise對象相同(但不相等)的新Promise對象。看以下例子:

// 不傳參的"then"
let p1 = Promise.resolve('resolve');
let p2 = p1.then();
p2.then(res => {
  console.log(res);       // 'resolve'
});
console.log(p1 === p2);   // false
// 不傳參的"catch"
let p3 = Promise.reject('reject');
let p4 = p3.catch();
p4.catch(res => {
  console.log(res);       // 'reject'
});
console.log(p3 === p4);   // false
// 不傳參的"finally"
let p5 = Promise.resolve('resolve');
let p6 = p5.finally();
p6.then(res => {
  console.log(res);       // 'resolve'
});
console.log(p5 === p6);   // false
複製代碼

then()/catch()/finally() 的參數是帶返回值的回調函數

then()catch()的參數是有返回值的回調函數Athen()catch()返回一個狀態爲fulfilledPromise對象。新Promise對象的then()方法的回調函數的參數就是回調函數A的返回值。

注意,狀態爲rejectPromise對象在then()的第一個對調函數返回會致使報錯。

注意,finally()的對調函數"return"並不會影響新的Promise對象的then()catch()方法的回調函數的參數值。

若是以爲文字描述有點繞,看下面例子:

// 'resolve'狀態被處理後的'return'
Promise.resolve('resolve').then(() => {
  return 'return1'
}).then(res => {
  console.log(res)
});   // 'return1'
// 'reject'狀態被處理後的'return'
Promise.reject('resolve').catch(() => {
  return 'return2'
}).catch(err => {
  console.log('catch:', err)
}).then(res => {
  console.log('then:', res)
});   // 'then: return2'
// 'finally'的'return'只會返回與原promise相同的對象
Promise.resolve('resolve').finally(() => {
  return 'return3'
}).then(res => {
  console.log(res)
});   // 'resolve'
// 'reject'狀態未被處理的'return'
Promise.reject('reject').then(() => {
  return 'return4'
}).then(res => {
  console.log(res);
});   // 報錯!!複製代碼

.resolve() 的參數

resolve()(包括Promise.reject()Promise.prototype.reject())除了上面介紹的用法,還能傳入thenable(即,帶有then方法的對象),返回的Promise對象的最終狀態由then方法執行決定。

注意,thenablethen()方法只有傳入惟一一個回調函數纔會被執行,其餘參數會被忽略。

看以下例子:

let thenable = {
  then(cb1, cb2) {
    cb1('cb1');
    cb2('cb2');
  }
}
// Promise.resolve()
Promise.resolve(thenable).then(
  res1 => {
    console.log(res1);  // 'cb1'
  },
  res2 => {
    console.log(res2);  // 不會執行
  }
).catch(err => {
  console.log(err);     // 不會執行
});
// Promise.prototype.resolve()
new Promise((resolve, reject) => {
  resolve(thenable);
}).then(res => {
  console.log(res);     // 'cb1'
});複製代碼
相關文章
相關標籤/搜索