1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          promises(Promises的重點是什么)

          來源:互聯網轉載 時間:2024-05-11 19:16:53

          迄今為止,可能每個JavaScript開發者和他們的祖母都聽說過Promises。如果你沒有,那么你即將會。promises的概念是由CommonJS小組的成員在 Promises/A規范 中提出來的。Promises被逐漸用作一種管理異步操作回調的方法,但出于它們的設計,它們遠比那個有用得多。事實上,由于它們的多種用法,有無數人告訴我&mdash;&mdash;在我寫過一些關于promises的東西后&mdash;&mdash;我“遺漏了promises的重點”。那么什么是promises的重點呢?

          一點關于Promises的東西

          在我開始promise的“重點”之前,我想我應該給你一點它們如何工作的內貌。一個promise是一個對象&mdash;&mdash;根據Promise/A規范&mdash;&mdash;只需要一個方法:then。then方法帶有三個參數:一個成功回調,一個失敗回調,和一個前進回調(規范沒有要求包括前進回調的實現,但是很多都實現了)。一個全新的promise對象從每個then的調用中返回。

          一個promise可以是三種狀態之一:未完成的,完成的,或者失敗的。promise以未完成的狀態開始,如果成功它將會是完成態,如果失敗將會是失敗態。當一個promise移動到完成態,所有注冊到它的成功回調將被調用,而且會將成功的結果值傳給它。另外,任何注冊到promise的成功回調,將會在它已經完成以后立即被調用。

          同樣的事情發生在promise移動到失敗態的時候,除了它調用的是失敗回調而不是成功回調。對包含前進特性的實現來說,promise在它離開未完成狀態以前的任何時刻,都可以更新它的progress。當progress被更新,所有的前進回調(progress callbacks)會被傳遞以progress的值,并被立即調用。前進回調被以不同于成功和失敗回調的方式處理;如果你在一個progress更新已經發生以后注冊了一個前進回調,新的前進回調只會在它被注冊以后被已更新的progress調用。

          我們不會進一步深入promise狀態是如何管理的,因為那不在規范之內,而且每個實現都有差別。在后面的例子中,你將會看到它是如何完成的,但目前這就是所有你需要知道的。

          處理回調

          像前面提到的為異步操作處理回調,是promises的最基本和最普通的用途,讓我們將一個標準的回調與一個采用了promise的回調比較一下。

          回調

          //NormalcallbackusageasyncOperation(function(){//Here'syourcallback});//Now`asyncOperation`returnsapromiseasyncOperation().then(function(){//Here'syourcallback});

          我很懷疑只是看到這個例子的話是否有人會真的關心去使用promises??雌饋頉]有什么好處,除了“then”使得在異步操作完成之后的回調函數被調用這件事看起來更加明顯。但是即使是這個好處,我們現在有了更多的代碼(抽象應該使我們的代碼更短,不是嗎?)而且promise比標準回調稍微性能差一點。

          但是,不要讓這阻礙到你。如果這就是promise可以做的最好的事,這篇文章就不會存在了。

          厄運的金字塔

          網上你可以找到很多文章引用“厄運的金字塔”的說法作為使用promises的主要原因。這是指需要連續的執行多個異步操作。在普通回調下,我們將會在相互的調用之間結束嵌套的調用;隨著這種調用代碼變得更縮進,生成了一個金字塔(指向右方的)因此有了“厄運的金字塔”的名字。如果你只需連續執行一兩個異步操作,那么這還不是太壞,但一旦你需要做3個或更多,它將會變得難以閱讀,特別是當每一步都有相當多的處理需要做的時候。使用promises可以幫助代碼變平,而且使它再一次變得更容易閱讀。我們來看看。

          厄運的金字塔

          //Normalcallbackusage=>PYRAMIDOFDOOOOOOOOMasyncOperation(function(data){//Dosomeprocessingwith`data`anotherAsync(function(data2){//Somemoreprocessingwith`data2`yetAnotherAsync(function(){//Yaywe'refinished!});});});//Let'slookatusingpromisesasyncOperation().then(function(data){//Dosomeprocessingwith`data`returnanotherAsync();}).then(function(data2){//Somemoreprocessingwith`data2`returnyetAnotherAsync();}).then(function(){//Yaywe'refinished!});

          正如你所見,promises的使用使得事情變扁平而且更可讀了。這能起作用是因為&mdash;&mdash;像早先提到的&mdash;&mdash;then返回了一個promise,所以你可以將then的調用不停的串連起來。由then返回的promise裝載了由調用返回的值。如果調用返回了一個promise(像這個例子中的情形一樣),then返回的 promise裝載了與你的回調返回的promise所裝載的相同值。這內容很多,因此我將幫助你一步一步的理解它。

          異步操作返回一個promise對象。因此我們在那個promise對象中調用then,并且傳給它一個回調函數;then也會返回一個promise。當異步操作結束,它將給promise裝上數據。然后(第一次)回調被調用,數據被作為參數傳遞進去。如果回調不含有返回值,then返回的promise將會立即不帶值組裝。如果回調返回的不是一個promise,那么then返回的 promise將會立即裝載那個數值。如果回調返回一個promise(像例子中的),那么then返回的 promise將等待直到我們回調返回的promise被完全裝載。一旦我們回調的 promise被裝載,它裝載的值(本例中就是data2)將會被提交給then的promise。然后then中的promise裝載了data2。等等。聽起來有點復雜,但事實上很簡單,如果我說的你不能理解,我非常抱歉。我猜我可能不是談論它的最佳人選。

          用命名的回調替代

          但顯然 promises 不是使這個結構扁平化的唯一方法。在寫了一篇提到promises解決了厄運的金字塔問題的帖子之后,有個人對該帖評論說&hellip;&hellip;

          我想promises有時是有用的,但是“嵌套”的回調的問題(圣誕樹綜合癥)可以僅用一個命名的函數作為一個參數替代匿名函數的方法平常的處理:

          asyncCall( param1, param2, HandlerCallback );

          function HandlerCallback(err, res){
          // do stuff
          }

          它的例子只是給出了一層深的例子,但它仍是正確的。我們來擴展我前面的例子,使這個看起來容易些。

          命名回調

          //Normalcallbackusage=>PYRAMIDOFDOOOOOOOOMasyncOperation(handler1);functionhandler1(data){//Dosomeprocessingwith`data`anotherAsync(handler2);}functionhandler2(data2){//Somemoreprocessingwith`data2`yetAnotherAsync(handler3);}functionhandler3(){//Yaywe'refinished!}

          看看上面的代碼!他們絕對是對的!它就是一個扁平的結構,但是這里有個問題同樣也存在于 我以前從來沒有注意過的老的回調例子中:依賴性和復用性。依賴性和復用性是相互關聯的可逆類型。一樣東西依賴的越少,那么它的復用性就越大。在以上的例子中,handler1依賴handler2,handler2依賴handler3.這就意味著handler1無論出于任何目的都不可在被用除非handler2也呈現出來。假如你不打算重用他們,那么給你的函數命名又有什么意義呢?

          最糟糕的的是handler1都不關心在handler2里面發生了什么事情。它壓根就不需要handler2除了和它異步工作。因此,讓我們消除這些依賴性然后通過用promise使函數更具復用性。

          鏈式回調

          asyncOperation().then(handler1).then(handler2).then(handler3);functionhandler1(data){//Dosomeprocessingwith`data`returnanotherAsync();}functionhandler2(data2){//Somemoreprocessingwith`data2`returnyetAnotherAsync();}functionhandler3(){//Yaywe'refinished!}

          這樣看起來是不是好多了?假如另外的函數存在的話,現在handler1和handler2都互不相關了。想看看他們是否真的很棒呢?現在handler1可以被用在不需要handler2的情況下了。相反,handler1被操作以后,我們將可以用另一個handler。

          復用函數

          asyncOperation().then(handler1).then(anotherHandler);functionhandler1(data){//Dosomeprocessingwith`data`returnanotherAsync();}functionanotherHandler(data2){//Dosomereallyawesomestuffthatyou'veneverseenbefore.It'llimpressyou}

          現在handler1已經從handler2脫離而且可以被用在了更多的情形中,特別是那些由handler2提供的功能而我們又不想用的。這就是復用性!評論家解決代碼易讀性的唯一方法就是通過消除縮進。我們不想消除縮進僅僅是為了縮進。多層次的縮進僅僅是某些事情錯誤的標志,問題不一定在它本身。他就像是由脫水引起的頭痛。真正的問題是脫水,不是頭痛。解決的方法是獲得水合物,而不是用一些止痛藥。

          并行異步操作

          在前面我提到的文章里,我將promises與events在處理異步操作方面做了比較。遺憾的是,按照那些曾提到過的人在評論里給的說法,我比較的不是很成功。我描述出了promises的力量,接著轉到events來描述它們的力量,就像在我的特別項目里用到的那樣。沒有比較和對比。一位評論者寫道(修改了一點語法錯誤):

          我想用帖子中的例子是一個壞的對照。有篇論文證明了promises的值將會怎樣,如果按下虛構的“啟動服務器按鈕”,將不僅僅是啟動一個web服務器,還有一個數據庫服務器,當它們都在運行的時候只是更新了UI。

          使用promise的.when方法將會使這種“多個異步操作”例子變得普通,然而響應多個異步事件需要一個并不普通的代碼量。

          他完全正確。事實上我沒有比較那兩種情況。那篇文章的要點實際在于說明promises不是異步操作的唯一機制,而且在一些情況下,它們也不一定是最好的。在這個評論者指出的情況下,promises當然是最佳的解決辦法。我們來看看他說的是什么。

          jQuery 具有 一個名為when的方法 ,可以帶上任意數量的promise參數,并返回一個單一的promise。如果任何一個promise傳入失敗,when返回的promise也會失敗。如果所有的promises被裝載,那么每個值都將會按照promises被定義的順序傳遞給附加的回調。

          以并行的方式執行無數的異步操作非常有用,然后只要在它們之中的每一個結束之后繼續執行回調。我們看一個簡單的例子.

          jQuery.when

          //Eachoftheseasyncfunctionsreturnapromisevarpromise1=asyncOperation1();varpromise2=asyncOperation2();varpromise3=asyncOperation3();//The$referstojQuery$.when(promise1,promise2,promise3).then(function(value1,value2,value3){//Dosomethingwitheachofthereturnedvalues});

          人們經常說這是 promises 帶來的最好的東西之一,也是 promises 的一部分重要的意義所在。我也認為這是個簡化了大量操作的好特性,但是這種 when 方法的機制 根本就沒有在任何 Promises 規范中提到,所以我不認為它是 Promises意義所在。有一個規范提到了 when 方法,但是和上面的完全不同。就我所知,jQuery 是唯一的實現了這種 when 方法的庫。其他的 promises 庫,例如 Q, Dojo, 和 when依照 Promises/B spec實現了 when 方法, 但是并沒有實現注釋者提及的 when 方法。但是,Q 庫有一個 all方法,when.js 也有一個 parallel方法,與上面的 jQuery.when 方法作用一樣,只是它們接受一個數組類型的參數,而不是任意數量的參數。

          值的表示

          另一個評論者給我留言:

          Promise是處理以下場景的更好的方法:

          "我想在這個數據庫中找一個用戶,但find方法是異步的。"

          因此,這里我們有了一個不能立刻返回值的find方法。但最終它確實"返回"了一個數值(通過一個回調的方式),而你希望以某種方式處理那個數值?,F在,通過使用一個回調,你能定義一個繼續部分,或者說“一些將在以后時間里處理那個數值的代碼”

          Promise改變了那種“嘿,這里是一些你會發現你用來處理返回數值的代碼”。它們是一些允許"find"方法說“嘿,我將忙著找你要找的信息,但與此同時你能繼續等著返回結果,而且你能同時以任何你希望的方式處理它,就像實際的東西!”

          Promise代表了真實的數值。那就是陷阱。它們工作在你像處理實際東西一樣處理Promise的時候。Promise的JavaScript實現期待你給它傳遞一個回調函數,這只是一個“巧合”,它不是重要的事情。

          我相信這真的就是promise的重點。為什么?讀一讀 Promise/A規范 的第一句“一個promise代表了一個操作的一次完成最終返回的數值?!笆顾悬c明顯了,是不是?好吧,即使那就是重點,那也不能阻止我在后面本文中呈現其他人的見解。不管怎么說,我們再多談論這個思想一點。

          這個概念是美好的,但它在實踐中是如何體現的?把promises看作數值的表現形式看起來像什么?首先,讓我們來看看一些同步的代碼:

          Synchronous Code

          //Searchacollectionforalistof"specific"itemsvardataArray=dataCollection.find('somethingSpecific');//MapthearraysothatwecangetjusttheID'svarids=map(dataArray,function(item){returnitem.id;});//Displaythemdisplay(ids);

          好的,如果dataCollection.find是同步的,這段代碼能正常工作。但是如果它是異步的呢?我的意思是看看這段代碼;它完全是同步方式寫的。如果find是異步的,沒有方法能保證運行正確,對不?不對。我們僅需修改map和display,接受promises作為參數,代表用作計算的數據。同樣,find和map需要返回promises。所以假設dataCollectionque確實不包含數據:僅僅只是調用AJAX獲取數據。所以現在將返回一個promise?,F在,讓我們重寫map和display,接受promises,但是我們取不同的名字:pmap和pdisplay。

          接受Promise作為參數

          functionpmap(dataPromise,fn){//Alwaysassume`dataPromise`isapromise...cutsdownonthecode//`then`returnsapromise,solet'susethatinsteadofcreatingourownreturndataPromise.then(//Successcallbackfunction(data){//Fulfillourpromisewiththedatareturnedfromthenormalsynchronous`map`returnmap(data,fn);}//Passerrorsthroughbynotincludingafailurecallback);}functionpdisplay(dataPromise){dataPromise.then(//Successcallbackfunction(data){//Whenwehavethedata,justsendittothenormalsynchronous`display`display(data);},//Failurecallbackfunction(err){//Ifitfails,we'lljustdisplaytheerrordisplay(err);});}

          這不會太難, 是嗎? 讓我們現在用這些新函數重新編寫上面那個例子:

          異步代碼

          //Searchacollectionforalistof"specific"itemsvardataArray=dataCollection.find('somethingSpecific');//MapthearraysothatwecangetjusttheID'svarids=pmap(dataArray,function(item){returnitem.id;});//Displaythempdisplay(ids);

          我所要做的是修改這些函數的名字。假如你很自信,你完全可以用相同的名字編寫這些函數,接受一個promise或者普通值,做出相應的反應。在新代碼中,這些promise表示返回的最終值,所以我們能以promise看起來像真實值的方式來編寫代碼。

          我撒了點小謊。上面我說過“這會工作得完全一樣”,但這是個棘手的問題。除了一些函數的名字改變了,這里還有一些別的不同:在調用pdisplay之后出現的任何代碼,有可能在實際的顯示發生之前被調用。所以你要么需要使后面的代碼不依賴于顯示的結束,要么需要從pdisplay返回一個promise,并且使其他的代碼在promise被裝載之后運行。在我的例子中沒有使pdisplay返回一個promise的一部分原因是,它沒有返回的數值,因此在我們討論本節中,promise不能被用來表示成一個數值。

          不管怎樣,你可以看到如何使你的函數接受promise,而不只是普通的數值,可以使你的代碼看起來更干凈更靠近像同步代碼一樣工作。那是promise的一個美妙之處。在Jedi Toolkit的博客上,從一個略微不同的觀點,有另一個關于這個概念的帖子。

          為了流暢的API內部使用

          某人評論我的文章說:

          我想在解釋promise是做什么的方面,我們寫promise實現的那些人做得很糟糕。我的觀點是,你作為一個用戶永遠都不應該被迫與promise用then()交互。then()是promise消費庫用來相互之間交互,并且提供流暢的API的一種途徑。你應該仍然像通常一樣使用回調與事件。

          他的評論非常好的契合了前面關于使用promise代表數值的一節。通過使用promise代表數值,我們能夠創建簡單的像上面看到的API,但這里我們在討論一個鏈接的API。根本上說,這個評論者是在告訴我們,要在一個異步命令鏈的末尾使用回調,以便我們仍然在做我們過去習慣做的(在末尾使用回調),而無人能說出我們在使用promise。他想使promise遠離普通用戶,只在我們自己庫的內部使用??匆幌逻@個查詢數據庫,并越來越異步過濾結果的例子。

          Chained .then Calls

          database.find().then(function(results1){returnresults1.filter('name','Joe');}).then(function(results2){returnresults2.limit(5);}).then(function(resultsForReal){//Dostuffwiththeresults});

          不論什么原因,filter和limit其實是異步的。 可能你覺得它們不應該這樣,但是它們就是這樣的。好了,評論家建議修改 API,保證用戶可以這樣使用:

          順暢的API例子

          database.find().filter('name','Joe').limit(5,function(results){//Dostuffwiththeresults});

          這對我似乎更有意思。如果你能掌控它的運行,這是你應當采取的線路。你可以修改一點, 替代普通的回調,仍然返回promise:

          返回Promise

          varresults=database.find().filter('name','Joe').limit(5);results.then(function(realResults){//Dostuffwiththeresults});//ORuseresultslikeintheprevioussection:doStuffWith(results);

          選擇權在你。我認為老道的開發者明白返回promise給用戶沒有什么問題,但這確實是個見仁見智的問題。無論哪種方式,都比我們需要先串起再調用的情況好許多。

          同步并行的錯誤隔離

          有一篇相當著名的文章叫做You're Missing the Point of Promises,和本文觀點一致。那篇文章中,Domenic Denicola(押頭韻的好名字)指導了部分關于then函數的Promises/A規范。

          then(fulfilledHandler, errorHandler, progressHandler)

          添加了fulfilledHandler、errorHandler和progressHandler,這三個處理函數在promise完成時被調用。Promise完成時,調用fulfilledHandler。Promise失敗時,調用errorHandler。觸發postgress事件時,調用progressHandler。所有參數都是可選的,并且非函數類型的值會被忽略。不僅progressHandler參數是可選的,而且progress也是完全可選的。Promise的實現者們不必要在任何時候調用progressHandler,如果有postgress事件到來就調用它。

          給出的fulfilledHandler和errorHandler回調函數完成時,此函數應當返回一個成功的新promise。這就允許promise操作串起來?;卣{函數handler的返回值是返回promise的完成值。如果回調函數拋出錯誤,那么返回的promise會被移交到失敗狀態。

          在他的文章中,他在最后一段表明了用途,這是他稱之為的“最重要”的一段。他說:

          問題是,promises不是回調函數的聚集體。那是一種簡單的功用。Promises是更加深層的東西,具體說就是,它提供了同步和異步函數的直接對應。

          我完全同意這個觀點。然后他繼續特別地關注最后的那個句子:“如果回調函數拋出一個錯誤,返回的promise將會轉為失敗狀態?!彼P注這個句子的原因是jQuery的實現可能實現了Promises/A規范,但沒有這樣做。如果一個錯誤在回調函數里拋出,它在promise的實現里變得不可捕獲。

          對于大多數人來說這點是非常重要的,盡管我還沒有遇到這種情況,這種情況確實是個問題,因為我不經常拋出錯誤。錯誤的promise等價于一個錯誤或者異常,所以,如果錯誤存在,這時應該是失敗而不是拋出一個錯誤。這種方法下我們能夠繼續使用promise來并行同步操作。我認為我們都應該把這個bug報告給jQuery。更多的人去報告這錯誤,就更可能快的被修復。jQuery的promise是最常使用的實現之一,所以我們應該確定他們的做法是正確的。

          不管怎樣,promise的重點是它代表一個操作返回的最終結果值,但使用它們的原因是使同步操作更好的并行。自從異步編程進入此場景,到處都是彈出的回調,以奇怪的方式遮住我們的代碼。Promise是一種改變其的方法。Promise允許我們以同步的方式寫代碼,同時給予我們代碼的異步執行。

          關于Promises的重點是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注本站行業資訊頻道了解更多相關知識。

          標簽:promises-

          c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...

          2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...

          :喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...

          三類股東是什么意思?三類股東指的是契約型私募基金、資產管理計劃、信托計劃。而三類股東企業是指直接或間接投資人中有三類股東的企業。三類股東開展業務的話,一般是以管理人的身份。不過在開展業務期間,也會存在一些問題,比如信息披露、核查缺乏第三方證據、稅收等。不出資可以成為股東嗎?一般情況下,成為公司的股東是需要出資的,只不過出資方式有可能不同,有用貨幣出資的,也可以用實物、知識產權、土地使用權等可以用貨...

          【資料圖】關于金絲楠木手串怎么盤的知識大家了解嗎?以下就是小編整理的關于金絲楠木手串怎么盤的介紹,希望可以給到大家一些參考,一起來了解下吧!在盤玩金絲楠木手串的時候,一般手心經常出汗的人建議戴棉質手套盤玩,避免汗液內的鹽和脂肪酸影響金絲楠木手串的光澤度。再放在纖維布內一顆一顆揉搓,這樣盤玩時間久了可以讓金絲楠木手串表面變得細膩有光澤。金絲楠木手串的盤玩方法剛購買回來的金絲楠木手串最好不要直接上手盤...

          另類投資市場是什么意思?英文 Alternative Investment Market的縮寫,指英國為那些不夠資格在倫敦股票交易所正式上市的公司所設的市場,這些公司通常是規模較小或高風險的企業。另類投資的投資范圍有哪些?另類投資包括房地產、證券化資產、對沖基金、私人股本基金、大宗商品、藝術品。另類投資是指投資于傳統的股票、債券和現金之外的金融和實物資產,其中證券化資產就包括了次級房貸為基礎的債券...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>