初步瞭解Promise

問題來了

Promise 有幾種狀態?
Promise 有什麼優缺點?
Promise構造函數是同步仍是異步執行,then呢?
Promise和setTimeout的區別?
如何實現 Promise.all?
如何實現 Promise.finally?es6

Promise知識點

1. Promise

1)定義
保存着某個將來纔會結束的事件(異步操做)的容器數組

2)特色
(1)對象的狀態不受外界影響。三個狀態:pending(進行中)、fulfilled(已成功)、rejected(已失敗)。只有異步操做的結果,能夠決定當前狀態。
(2)狀態只能改變一次,任什麼時候候都能獲得該結果。兩種狀態改變的狀況:pending->fulfilled、pending->rejected。狀態一直保持,給Promise對象添加回調函數,能獲得該結果。promise

3)優缺點
(1)能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數;Promise對象提供統一的接口,是的控制異常操做更加容易。
(2)沒法取消Promise,一旦新創建即執行;若不設置回調函數,則Promise內部拋出的異常反應不到外部;pending狀態沒法得知進展。異步

2. Promise.prototype.then()

1)定義
爲Promise實例添加狀態改變時的回調函數。.then(resolved的回調函數,rejected的回調函數[可選])函數

tips:
then方法返回的是一個新的Promise實例(不是原來的那個Promise實例),所以能夠鏈式,如:.then().then()。
採用鏈式的then,能夠指定一組按照次序執行的回調函數。post

3. Promise.prototype.catch()

1)定義
then(null, rehection)或.then(undefiend, rejection)的別名,用於指定發生錯誤時的回調函數。this

tips:
promise對象的錯誤具備「冒泡」性質,錯誤一直向後傳遞,直至被捕獲。
promise對象錯誤不會傳遞到外層代碼,即不一樣於try/catch,(報錯後不會終止外層代碼執行)。prototype

4. Promise.prototype.finally()

1)定義
不論Promise對象最終狀態如何,都會執行的操做(ES2018)。本質上是then方法的特例。
2)特色
不接受任何參數,不影響原Promise的狀態。
3)實際應用
post請求loading,在請求結束後不論結果如何都關閉loadingcode

5. Promise.all()

做用:
將多個Promise實例,包裝成一個Promise實例。對象

特色:
新Promise對象(p)的狀態由Promise實例數組([p1, p2, p3])決定。
當p一、 p二、 p3狀態都爲fulfilled,p的狀態爲fulfilled,p一、p二、p3的返回值組成一個數組,傳遞給p的回調函數。
當p一、 p二、 p3中有一個狀態爲rejected,p的狀態爲rejected,第一個被reject的實例的返回值,會傳遞給p的回調函數。

問題解答

1. Promise有幾種狀態

pending(進行中)、fulfilled(已成功)和rejected(已失敗)

2. Promise有什麼優缺點

能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數;Promise對象提供統一的接口,是的控制異常操做更加容易。
沒法取消Promise,一旦新創建即執行;若不設置回調函數,則Promise內部拋出的異常反應不到外部;pending狀態沒法得知進展。

3. Promise構造函數是同步仍是異步執行,then呢?

構造函數同步執行,then異步執行

4. Promise和setTimeout的區別

setTimeout(fn, 0)在下一輪「事件循環」開始時執行,Promise.then()在本輪「事件循環」結束時執行。

5.如何實現 Promise.all

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    let resultCount = 0;
    let results = new Array(promises.length);

    for (let i = 0; i < promises.length; i++) {
      promises[i].then(value => {
                resultCount++;
        results[i] = value;
        if (resultCount === promises.length) {
          return resolve(results)
        }
      }, error => {
        reject(error)
      })
    }
  })
}

let p1 = new Promise(resolve => resolve('p1'))
let p2 = new Promise(resolve => resolve('p2'))
let p3 = Promise.reject('p3 error')

Promise.all([p1, p2, p3]).then(results => {
  console.log(results)
}).catch(error => {
  console.log(error)      // 'p3 error'
})

promiseAll([p1, p2]).then(results => {
  console.log(results)    // ['p1', 'p2']
}).catch(error => {
  console.log(error)
})

6.如何實現 Promise.finally

Promise.prototype.finally = function (callback) {
  let P = this.constructor; // 構造函數
  console.log(P);
  return this.then(
    value  => P.resolve(callback()).then(() => value),  // resolve
    reason => P.resolve(callback()).then(() => { throw reason })  // reject
  );
};

參考文章

《ECMAScript 6 入門——阮一峯》

相關文章
相關標籤/搜索