javaScript中Promise深度理解

用途

用於處理異步操作,避免地獄式回調,比如ajax請求,處理起來更加簡單方便,代碼看起來也更容易理解,便於維護。

概念

Promise 對象用於表示一個異步操作的最終狀態(完成或失敗),以及其返回的值。 Promise共有三種狀態,相應狀態會觸發相應的回調函數。

  • pending: 初始狀態。什麼回調函數也不觸發。

    • 調用構造函數如new Promise((resolve, reject) => {}),在這個exextutor函數中要麼調用resolve是狀態改爲完成,要麼調用reject使狀態改爲失敗,要麼就什麼都不調用,這個時候就是pending狀態,此時[[PromiseValue]]undefined

          var result = new Promise((resolve, reject) => {
          
          })
    • .then.catch中返回值爲上面直接使用構造函數的情況,並且在其內部也什麼都不返回,那麼這個時候也是pending

          var result = new Promise((resolve, reject) => {
              resolve('xxx')
          }).then((res) => {
              return new Promise((resolve, reject) => {
          
              })
          })
    • .then.catch中無返回值的時候,這個時候返回的狀態爲前面的Promise的狀態,如果前面的狀態爲pending,那麼這裏返回的也是pending,只不過沒有返回值,返回的Promise[[PromiseValue]]undefined

          var result = new Promise((resolve, reject) => {
              
          }).then((res) => {
      
          })
  • fulfilled: 成功狀態。觸發綁定的‘onfulfilled’方法。

    • executor函數中調用resolve

        var result = new Promise((resolve, reject) => {
            resolve('xxx')
        })
    • .then .catch中調用Promsie.resolve

       var result = new Promise((resolve, reject) => {
             resolve('xxx')
       }).then((res) => {
           return Promise.resolve('bbbb')
       })
    • .then .catch中的返回值爲一個普通值,值作爲[[PromiseValue]]`的值。

       var result = new Promise((resolve, reject) => {
             resolve('xxx')
       }).then((res) => {
           return 'xxxx'
       })
    • .then.catch中無返回值的時候,這個時候返回的狀態爲前面的Promise的狀態,如果前面的狀態爲resolved,那麼這裏返回的也是resolved,只不過沒有返回值,返回的Promise[[PromiseValue]]undefined

          var result = new Promise((resolve, reject) => {
              resolve('xxx')
          }).then((res) => {
              
          })
  • rejected: 失敗狀態。觸發綁定的‘onrejected’方法。

    • executor函數中調用rejecte

        var result = new Promise((resolve, reject) => {
            reject('xxx')
        })
    • .then .catch中調用Promsie.reject

       var result = new Promise((resolve, reject) => {
             resolve('xxx')
       }).then((res) => {
           return Promise.reject('bbbb')
       })
    • .then .catch中拋出一個錯誤時,狀態改爲rejected,並且觸發onrejected函數,錯誤信息將作爲作爲拒絕狀態的回調函數的參數值和拒絕狀態的Promise[[PromiseValue]]的值。

       var result = new Promise((resolve, reject) => {
             resolve('xxx')
       }).then((res) => {
           throw 'xxxx'
       }).catch((err) => {
            console.log(err) // xxxx
       })
       console.log(result) // {[[PromiseStatus]]: "rejected",  [[PromiseValue]]: "xxxx"}

.then

p.then(onFulfilled, onRejected);

當狀態變成成功狀態的時候調用onFulfilled, 當狀態變成失敗的時候,調用onRejected。它返回一個Promise,而它的行爲與then中的回調函數的返回值有關:

  • 如果then中的回調函數返回一個值,那麼then返回的Promise將會成爲接受狀態,並且將返回的值作爲接受狀態的回調函數的參數值。
  • 如果then中的回調函數拋出一個錯誤,那麼then返回的Promise將會成爲拒絕狀態,並且將拋出的錯誤作爲拒絕狀態的回調函數的參數值。
  • 如果then中的回調函數返回一個已經是接受狀態的Promise,那麼then返回的Promise也會成爲接受狀態,並且將那個Promise的接受狀態的回調函數的參數值作爲該被返回的Promise的接受狀態回調函數的參數值。
  • 如果then中的回調函數返回一個已經是拒絕狀態的Promise,那麼then返回的Promise也會成爲拒絕狀態,並且將那個Promise的拒絕狀態的回調函數的參數值作爲該被返回的Promise的拒絕狀態回調函數的參數值。
  • 如果then中的回調函數返回一個未定狀態(pending)的Promise,那麼then返回Promise的狀態也是未定的,並且它的終態與那個Promise的終態相同;同時,它變爲終態時調用的回調函數參數與那個Promise變爲終態時的回調函數的參數是相同的。

Promise.resolve

參數可以是三種參數類型

  • Promise.resolve(value);
  • Promise.resolve(promise);
  • Promise.resolve(thenable);

如果參數類型是普通的值那麼返回的Promise狀態仍然是resolve,值爲返回的值,如果返回值是另外兩種情況,那麼返回的Promise的狀態由返回值來決定。例如下面的例子返回的是reject,值爲xxxx

        var result = Promise.resolve(new Promise((resolve, reject) => {
                reject('xxxx')
        }))

Promise.reject

接收一個參數,但是參數不會影響返回的Promise結果,通過Promise.reject返回的狀態始終都是reject

Promise.all

當我們需要並行執行多個異步的時候,就可以使用這個方法,該方法接收一個可以迭代的對象,例如數組,數組中一般都是我們需要並行運行的Promise對象,如果是普通值那麼也會直接返回。只有每一項都爲resolve時,纔會調用.then中的成功方法,並且回調參數值一個包含前面所有結果的數組,並且順序也和前面一樣,否則調用失敗的回調。看個例子

var a = 1
var b = new Promise((resolve, reject) => {
    setTimeout(function(){
        resolve('xxxx')
    }, 1000)
})
var c = Promise.resolve('aaa')
var result = Promise.all([a, b, c]).then((values) => {
    console.log(values) // 1, xxx, aaa
}).catch((err) => {
    console.log(err)
})

對於Promise.all的同步或者異步,如果值是空的可迭代對象,那麼將是同步的,其他情況均爲異步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章