<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          then, catch, finally如何影響返回的Promise實(shí)例狀態(tài)

          共 7306字,需瀏覽 15分鐘

           ·

          2020-12-19 15:22

          db7955352874b89f95a3ef6ada6f3774.webp

          點(diǎn)擊上方藍(lán)字“前端司南”關(guān)注我您的關(guān)注意義重大
          f2de9a94d8de5f0365727d3f55e51e65.webp原創(chuàng)@前端司南

          雖然Promise是開發(fā)過程中使用非常頻繁的一個(gè)技術(shù)點(diǎn),但是它的一些細(xì)節(jié)可能很多人都沒有去關(guān)注過。我們都知道,.then, .catch, .finally都可以鏈?zhǔn)秸{(diào)用,其本質(zhì)上是因?yàn)榉祷亓艘粋€(gè)新的Promise實(shí)例,而這些Promise實(shí)例現(xiàn)在的狀態(tài)是什么或者將來會(huì)變成什么狀態(tài),很多人心里可能都沒個(gè)底。我自己也意識(shí)到了這一點(diǎn),于是我通過一些代碼試驗(yàn),發(fā)現(xiàn)了一些共性。如果您對(duì)這塊內(nèi)容還沒有把握,不妨看看。

          閱讀本文前,您應(yīng)該對(duì)Promise有一些基本認(rèn)識(shí),比如:

          • Promisepending, fulfilled, rejected三種狀態(tài),其決議函數(shù)resolve()能將Promise實(shí)例的狀態(tài)由pending轉(zhuǎn)為fulfilled,其決議函數(shù)reject()能將Promise實(shí)例的狀態(tài)由pending轉(zhuǎn)為rejected。
          • Promise實(shí)例的狀態(tài)一旦轉(zhuǎn)變,不可再逆轉(zhuǎn)。

          本文會(huì)從一些測(cè)驗(yàn)代碼入手,看看Promise的幾個(gè)原型方法在處理Promise狀態(tài)時(shí)的一些細(xì)節(jié),最后對(duì)它們進(jìn)行總結(jié)歸納,加深理解!

          先考慮then的行為

          then的語法形式如下:

          p.then(onFulfilled[,?onRejected]);

          onFulfilled可以接受一個(gè)value參數(shù),作為Promise狀態(tài)決議為fulfilled的結(jié)果,onRejected可以接受一個(gè)reason參數(shù),作為Promise狀態(tài)決議為rejected的原因。

          • 如果onFulfilledonRejected不返回值,那么.then返回的Promise實(shí)例的狀態(tài)會(huì)變成fulfilled,但是伴隨fulfilledvalue會(huì)是undefined
          new?Promise((resolve,?reject)?=>?{
          ????resolve(1)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          • 如果onFulfilledonRejected返回一個(gè)值x,那么.then返回的Promise實(shí)例的狀態(tài)會(huì)變成fulfilled,并且伴隨fulfilledvalue會(huì)是x。注意,一個(gè)非Promise的普通值在被返回時(shí)會(huì)被Promise.resolve(x)包裝成為一個(gè)狀態(tài)為fulfilledPromise實(shí)例。
          new?Promise((resolve,?reject)?=>?{
          ????reject(2)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          ????return?'a?new?value'
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          • 如果onFulfilledonRejected中拋出一個(gè)異常,那么.then返回的Promise實(shí)例的狀態(tài)會(huì)變成rejected,并且伴隨rejectedreason是剛才拋出的異常的錯(cuò)誤對(duì)象e。
          new?Promise((resolve,?reject)?=>?{
          ????resolve(1)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          ????throw?new?Error('some?error?occurred.')
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          • 如果onFulfilledonRejected返回一個(gè)Promise實(shí)例p2,那么不管p2的狀態(tài)是什么,.then返回的新Promise實(shí)例p1的狀態(tài)會(huì)取決于p2。如果p2現(xiàn)在或?qū)硎?code style="font-size:14px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(19,148,216);">fulfilled,那么p1的狀態(tài)也隨之變成fulfilled,并且伴隨fulfilledvalue也與p2進(jìn)行resolve(value)決議時(shí)傳遞的value相同;
          new?Promise((resolve,?reject)?=>?{
          ????resolve(1)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          ????return?Promise.resolve('a?fulfilled?promise')
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })

          這個(gè)邏輯同樣適用于rejected的場(chǎng)景。也就是說,如果p2的狀態(tài)現(xiàn)在或?qū)硎?code style="font-size:14px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(19,148,216);">rejected,那么p1的狀態(tài)也隨之變成rejected,而reason也來源于p1進(jìn)行reject(reason)決議時(shí)傳遞的reason。

          new?Promise((resolve,?reject)?=>?{
          ????reject(1)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          ????return?new?Promise((resolve,?reject)?=>?{
          ????????setTimeout(()?=>?{
          ????????????reject('a?promise?rejected?after?3?seconds.')
          ????????},?3000)
          ????})
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          再考慮catch的行為

          catch的語法形式如下:

          p.catch(onRejected);

          .catch只會(huì)處理rejected的情況,并且也會(huì)返回一個(gè)新的Promise實(shí)例。

          .catch(onRejected)then(undefined, onRejected)在表現(xiàn)上是一致的。

          事實(shí)上,catch(onRejected)從內(nèi)部調(diào)用了then(undefined, onRejected)。

          • 如果.catch(onRejected)onRejected回調(diào)中返回了一個(gè)狀態(tài)為rejectedPromise實(shí)例,那么.catch返回的Promise實(shí)例的狀態(tài)也將變成rejected。
          new?Promise((resolve,?reject)?=>?{
          ????reject(1)
          }).catch(reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          ????return?Promise.reject('rejected')
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          • 如果.catch(onRejected)onRejected回調(diào)中拋出了異常,那么.catch返回的Promise實(shí)例的狀態(tài)也將變成rejected。
          new?Promise((resolve,?reject)?=>?{
          ????reject(1)
          }).catch(reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          ????throw?2
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          • 其他情況下,.catch返回的Promise實(shí)例的狀態(tài)將是fulfilled。
          最后看看finally

          不管一個(gè)Promise的狀態(tài)是fulfilled還是rejected,傳遞到finally方法的回調(diào)函數(shù)onFinally都會(huì)被執(zhí)行。我們可以把一些公共行為放在onFinally執(zhí)行,比如把loading狀態(tài)置為false。

          注意,onFinally不會(huì)接受任何參數(shù),因?yàn)樗鼜脑O(shè)計(jì)上并不關(guān)心Promise實(shí)例的狀態(tài)是什么。

          p.finally(function()?{
          ???//?settled?(fulfilled?or?rejected)
          });

          finally方法也會(huì)返回一個(gè)新的Promise實(shí)例,這個(gè)新的Promise實(shí)例的狀態(tài)也取決于onFinally的返回值是什么,以及onFinally中是否拋出異常。

          你可以通過修改以下代碼中的注釋部分來驗(yàn)證,不同的返回值對(duì)于finally返回的Promise實(shí)例的狀態(tài)的影響。

          new?Promise((resolve,?reject)?=>?{
          ????reject(1)
          }).then(value?=>?{
          ????console.log('resolution?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?occurred,?and?the?reason?is:?',?reason)
          ????return?Promise.resolve(2);
          ????//?return?Promise.reject(3)
          }).finally(()?=>?{
          ????//?return?Promise.resolve(4)
          ????//?return?Promise.reject(5)
          ????throw?new?Error('an?error')
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          },?reason?=>?{
          ????console.log('rejection?of?the?returned?promise?occurred,?and?the?reason?is:?',?reason)
          })
          then, catch, finally小結(jié)

          綜合以上來看,不管是.then(onFulfilled, onRejected),還是.catch(onRejected),或者是.finally(onFinally),它們返回的Promise實(shí)例的狀態(tài)都取決于回調(diào)函數(shù)是否拋出異常,以及返回值是什么。

          • 如果回調(diào)函數(shù)的返回值是一個(gè)狀態(tài)為rejectedPromise實(shí)例,那么.then, .catch.finally返回的Promise實(shí)例的狀態(tài)就是rejected。

          • 如果回調(diào)函數(shù)的返回值是一個(gè)還未決議的Promise實(shí)例p2,那么.then, .catch.finally返回的Promise實(shí)例p1的狀態(tài)取決于p2的決議結(jié)果。

          • 如果回調(diào)函數(shù)中拋出了異常,那么.then, .catch.finally返回的Promise實(shí)例的狀態(tài)就是rejected,并且reason是所拋出異常的對(duì)象e

          • 其他情況下,.then, .catch.finally返回的Promise實(shí)例的狀態(tài)將是fulfilled。

          如何理解then中拋出異常后會(huì)觸發(fā)隨后的catch

          由于.then會(huì)返回一個(gè)新的Promise實(shí)例,而在.then回調(diào)中拋出了異常,導(dǎo)致這個(gè)新Promise的狀態(tài)變成了rejected,而.catch正是用于處理這個(gè)新的Promise實(shí)例的rejected場(chǎng)景的。

          new?Promise((resolve,?reject)?=>?{
          ????resolve(1)
          }).then(value?=>?{
          ????console.log('resolution?of?the?returned?promise?occurred,?and?the?value?is:?',?value)
          ????var?a?=?b;?//?未定義b
          }).catch(reason?=>?{
          ????console.log('caught?the?error?occured?in?the?callback?of?then?method,?and?the?reason?is:?',?reason)
          })

          最關(guān)鍵一點(diǎn)就是要理解:每次.then, .catch, .finally都產(chǎn)生一個(gè)新的Promise實(shí)例。

          Promise和jQuery的鏈?zhǔn)秸{(diào)用區(qū)別在哪?

          上文也提到了,.then, .catch, .finally都產(chǎn)生一個(gè)新的Promise實(shí)例,所以這種鏈?zhǔn)秸{(diào)用的對(duì)象實(shí)例已經(jīng)發(fā)生了變化。可以理解為:

          Promise.prototype.then?=?function()?{
          ??//?balabala
          ??return?new?Promise((resolve,?reject)?=>?{
          ????//?if?balabala
          ????//?else?if?balabala
          ????//?else?balabala
          ??});
          }

          而jQuery鏈?zhǔn)秸{(diào)用是基于同一個(gè)jQuery實(shí)例的,可以簡單表述為:

          jQuery.fn.css?=?function()?{
          ??//?balabala
          ??return?this;
          }


          ?? 感謝支持

          本文主要是參考了MDN《你不知道的JavaScript(下卷)》上關(guān)于Promise的知識(shí)點(diǎn),簡單分析了.then, .catch, .finally中回調(diào)函數(shù)的不同行為對(duì)于三者返回的Promise實(shí)例的影響,希望對(duì)大家有所幫助。

          • 收藏吃灰不如現(xiàn)在就開始學(xué)習(xí),奧利給!
          • 如果您覺得本文有所幫助,請(qǐng)留下您的點(diǎn)贊關(guān)注支持一波,謝謝!
          • 快關(guān)注公眾號(hào)前端司南,與筆者一起交流學(xué)習(xí)吧!

          瀏覽 77
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字墓aV| 欧美性69 | 日韩精品人妻中文字幕蜜乳 | 精品一区二区视频在线观看 | 亚洲色欲av |