摘要:一個(gè)就像一個(gè)樂(lè)高玩具。問(wèn)題是不是你小時(shí)候玩兒的那個(gè)有趣,它們不是充滿想象力的打氣筒,也不是一種樂(lè)高玩具。這是對(duì)的并不是給開發(fā)者使用的,它們是給庫(kù)作者使用的。不會(huì)超過(guò)這兩種情況。第二個(gè)是根據(jù)第一個(gè)處理函數(shù)如何運(yùn)行來(lái)自動(dòng)變成狀態(tài)成功或者失敗。
原文地址:http://blog.getify.com/promis...
在 Part4:擴(kuò)展問(wèn)題 中,我討論了如何擴(kuò)展和抽象Promise是多么的常見,以及這中間的一些問(wèn)題。但是為什么promise對(duì)于開發(fā)者來(lái)說(shuō)不是足夠友好的呢?這就是它的設(shè)計(jì)用意嗎?
I"ve Got Friends In Low PlacesPromise被設(shè)計(jì)為低級(jí)別的構(gòu)建塊。一個(gè)promise就像一個(gè)樂(lè)高玩具。單個(gè)樂(lè)高只是一個(gè)有趣的玩具。但是如果把它們拼在一起,你會(huì)感受到更多的樂(lè)趣。
問(wèn)題是promise不是你小時(shí)候玩兒的那個(gè)有趣LEGO,它們不是充滿想象力的打氣筒,也不是Gandalf mini-figure(一種樂(lè)高玩具)。
都不是,promise只是你的簡(jiǎn)單老舊的4X2的磚塊。
這并不是使它們非常有用。但是它們是你箱子中最重要的組成部分之一。當(dāng)它們彼此分開時(shí)它們只是這么個(gè)東西,但是當(dāng)把它們整合在一起它們就會(huì)散發(fā)出光芒。
換句話說(shuō),promise本質(zhì)上是一個(gè)構(gòu)建在真實(shí)用戶之上的低級(jí)別的API。這是對(duì)的:promise并不是給開發(fā)者使用的,它們是給庫(kù)作者使用的。
你會(huì)從它們那收益許多,但是你很可能不是直接使用它們。你將會(huì)使用的是經(jīng)過(guò)許多庫(kù)組合包裝之后的結(jié)果。
控制 VS 值請(qǐng)?jiān)试S我矯正第一個(gè)最大的關(guān)于promise的誤解:它們不是真正關(guān)于流程控制的。
promise當(dāng)然可以鏈接在一起來(lái)變成近似異步流程控制的東西。但是最后證明它們并不像你想象的那樣擅長(zhǎng)這個(gè)任務(wù)。promises確實(shí)只是一個(gè)值的容器。這個(gè)值可能現(xiàn)在就存在也可能是未來(lái)的一個(gè)值。但是不管怎樣,它只是一個(gè)值。這是promise最有意義的好處之一。它們?cè)谥档纳厦鎰?chuàng)建了一個(gè)強(qiáng)大的抽象使得值不再是暫存的東西。換句話說(shuō),不管那個(gè)值現(xiàn)在是否存在,你都可以用同樣的方式使用promise。在這個(gè)系列的 第三部分 中,我討論過(guò)promise必須是不可變的,它們作為值的意義也是基于這個(gè)特點(diǎn)的。
promises就像狀態(tài)的小型的自包含的表現(xiàn)方式。它們是可組合的,也就意味著你全部的程序可以用它們來(lái)表示。
限制就像你不能奢望一個(gè)多帶帶的4X2的樂(lè)高可以變成一個(gè)跑車,讓promise成為你的異步流程控制機(jī)制也是一種奢望。
那么promises作為一個(gè)非暫存的不可變的值對(duì)于解決異步任務(wù)意味著什么呢?在它們?cè)O(shè)計(jì)哲學(xué)的約束中,有它們擅長(zhǎng)并且可以有幫助的東西。
在剩下的內(nèi)容中,我會(huì)討論這個(gè)限制。但是我并不打算作為一個(gè)promise的批判者。我試圖去強(qiáng)調(diào)擴(kuò)展和抽象的重要性。
錯(cuò)誤處理當(dāng)我說(shuō)promise只是一個(gè)值的容器的時(shí)候我撒了個(gè)小慌。實(shí)際上,它是一個(gè)成功值或者失敗信息的容器。在任何時(shí)候,一個(gè)promise是一個(gè)未來(lái)的成功值或者在獲取這個(gè)值時(shí)的失敗信息。不會(huì)超過(guò)這兩種情況。
在某種意義上說(shuō),一個(gè)promise是一個(gè)決策結(jié)構(gòu),一個(gè)if..then..else。其他人喜歡把它想成一個(gè)try..catch結(jié)構(gòu)。不管是哪種理解,你就像在說(shuō)"請(qǐng)求一個(gè)值,不管成功還是失敗"。
就像尤達(dá)說(shuō),"Do or do not, there is no try"。
考慮下面這個(gè)情況:
function ajax(url) { return new Promise( function(resolve,reject){ // make some ajax request // if you get a response, `resolve( answer )` // if it fails, `reject( excuses )` } ); } ajax( "http://TheMeaningOfLife.com" ) .then( winAtLife, keepSearching );
看到winAtLife()和keepSearching()函數(shù)了嗎?我們?cè)谡f(shuō),"去問(wèn)問(wèn)生命的意義,不管你有沒(méi)有找到答案,我們都繼續(xù)"。
如果我們不傳入keepSearching會(huì)怎樣?除了作為一個(gè)樂(lè)觀主義者假設(shè)你會(huì)找到答案然后在生命長(zhǎng)河中取勝,這里會(huì)有什么危險(xiǎn)呢?
如果promise沒(méi)有找到生命的意義(或者如果在處理答案的過(guò)程中發(fā)生了javascript異常),它會(huì)默默地保留著錯(cuò)誤的事實(shí),也許會(huì)永遠(yuǎn)保留著。就算你等上一百萬(wàn)年,你都不會(huì)知道對(duì)于答案的請(qǐng)求失敗了。
你只能通過(guò)觀察才能知道它失敗了。這可能需要深入到形而上學(xué)或者量子學(xué)的東西。讓我們停止在這吧。
所以不帶失敗處理函數(shù)的promise是一個(gè)會(huì)默默地失敗的promise。這并不好。這意味著如果你忘記了,你會(huì)陷入失敗的陷阱而不是成功。
所以你會(huì)懷疑:為什么promises會(huì)忽略失敗處理函數(shù)呢?因?yàn)槟憧赡墁F(xiàn)在不在意失敗的情況,只有以后某個(gè)時(shí)刻會(huì)關(guān)心。我們程序的暫時(shí)性意味著系統(tǒng)現(xiàn)在不會(huì)知道你以后會(huì)想做什么。現(xiàn)在忽略失敗處理函數(shù)也許對(duì)你來(lái)說(shuō)是正合適的,因?yàn)槟阒滥銜?huì)把這個(gè)promise鏈接到另一個(gè)promise,并且那個(gè)promise有一個(gè)失敗處理函數(shù)。
所以promise機(jī)制讓你可以創(chuàng)建不需要監(jiān)聽失敗的promise。
這里有一個(gè)很微妙的問(wèn)題,很可能也是大多數(shù)剛接觸promise的開發(fā)者會(huì)碰到的問(wèn)題。
束縛我們的鏈子為了理解這個(gè)問(wèn)題,我們首先需要理解promises是如何鏈接在一起的。我認(rèn)為你會(huì)很快明白promise鏈?zhǔn)菑?qiáng)大并且有一點(diǎn)復(fù)雜的。
ajax( "http://TheMeaningOfLife.com" ) .then( winAtLife, keepSearching ) // a second promise returned here that we ignored! ;
ajax(..)調(diào)用產(chǎn)生了第一個(gè)promise,然后then(..)調(diào)用產(chǎn)生了第二個(gè)promise。我們沒(méi)有捕捉并且觀察在這段代碼中的第二個(gè)promise,但是我們可以。第二個(gè)promise是根據(jù)第一個(gè)promise處理函數(shù)如何運(yùn)行來(lái)自動(dòng)變成fulfilled狀態(tài)(成功或者失敗)。
第二個(gè)promise不會(huì)在意第一個(gè)promise是成功還是失敗。它在意第一個(gè)promise的處理函數(shù)(不管成功還是失敗)。
這是promise鏈的關(guān)鍵。但是這有一點(diǎn)不好理解,所以重復(fù)讀上面那段話直到你理解為止。
考慮下promise代碼通常是怎么寫的(通過(guò)鏈):
ajax( ".." ) .then( transformResult ) .then( displayAnswer, reportError );
這段代碼也可以像下面這么寫,效果是一樣的:
var promiseA = ajax( ".." ); var promiseB = promiseA.then( transformResult ); var promiseC = promiseB.then( displayAnswer, reportError ); // we don"t use `promiseC` here, but we could...
Promise A是唯一在意ajax(..)結(jié)果的promise。
Promise B只關(guān)心Promise A在transformResult(..)函數(shù)內(nèi)部是如何處理的(不是Promise A的結(jié)果本身),同樣的,Promise C只關(guān)心Promise B在displayAnswer(..)或者reportError(..)函數(shù)內(nèi)部是如何處理的(不是Promise B結(jié)果本身)。
再一次,重復(fù)讀這段話直到理解。
在transformResult(..)內(nèi)部,如果它立刻完成了它的任務(wù),然后Promise B就會(huì)立刻完成,不管成功還是失敗。然而,如果transformResult(..)不能立刻完成,而是創(chuàng)建它自己的promise,我們稱它為Promise H1("H"是"hidden",因?yàn)樗请[藏在內(nèi)部的)。原本Promise B返回的等待我們?nèi)绾翁幚鞵romise A的promise,現(xiàn)在概念上被Promise H1替換了(并不是真的替換了,只是被說(shuō)成一樣的)。
所以,現(xiàn)在當(dāng)你說(shuō)promiseB.then(..)時(shí),它實(shí)際上就像說(shuō)promiseH1.then(..)。如果Promise H1成功了,displayAnswer(..)會(huì)被調(diào)用,但是如果它失敗了,reportError(..)會(huì)被調(diào)用。
這就是promise鏈?zhǔn)侨绾喂ぷ鞯摹?/p>
但是,如果Promise A(由ajax調(diào)用返回)失敗了會(huì)怎樣?promiseA.then(..)調(diào)用沒(méi)有注冊(cè)一個(gè)失敗處理函數(shù)。它會(huì)默默地隱藏錯(cuò)誤嗎?它會(huì)的,除了我們鏈接上Promise B然后在上面注冊(cè)一個(gè)錯(cuò)誤處理函數(shù):reportError(..)。如果Promise A失敗了,transformResult(..)不會(huì)被調(diào)用,并且沒(méi)有錯(cuò)誤處理函數(shù),所以Promise B馬上被標(biāo)記為失敗,所以reportError(..)會(huì)被調(diào)用。
如果Promise A成功了,transformResult(..)會(huì)被執(zhí)行,然后當(dāng)運(yùn)行transformResult(..)時(shí)有一個(gè)錯(cuò)誤會(huì)怎樣?Promise B被標(biāo)記為失敗,然后reportError(..)也會(huì)被調(diào)用。
但是這里是危險(xiǎn)的地方,這個(gè)地方甚至有經(jīng)驗(yàn)的開發(fā)者都會(huì)遺漏的!
如果Promise A成功了(成功的ajax(..)),然后Promise B成功了(成功的transformResult(..)),但是當(dāng)運(yùn)行displayAnswer(..)時(shí)有一個(gè)錯(cuò)誤會(huì)怎樣?
你也許會(huì)認(rèn)為reportError(..)會(huì)被調(diào)用?大多數(shù)人會(huì)這么想,但是不是的。
為什么?因?yàn)閬?lái)自displayAnswer(..)的一個(gè)錯(cuò)誤或者失敗promise導(dǎo)致一個(gè)失敗的Promise C。我們監(jiān)聽Promise C失敗的情況了嗎?仔細(xì)看看。沒(méi)有。
為了確保你不會(huì)漏掉這種錯(cuò)誤并且讓它默默地隱藏在Promise C狀態(tài)內(nèi)部,你也會(huì)希望監(jiān)聽Promise C的失敗:
var promiseC = promiseB.then( displayAnswer, reportError ); // need to do this: promiseC.then( null, reportError ); // or this:, which is the same thing: promiseC.catch( reportError ); // Note: a silently ignored *Promise D* was created here!
OK,所以現(xiàn)在我們捕獲displayAnswer(..)內(nèi)部的錯(cuò)誤。不得不去記住這個(gè)有一點(diǎn)坑爹。
烏龜但是有一個(gè)更加微妙的問(wèn)題!如果當(dāng)處理displayAnswer(..)返回的錯(cuò)誤時(shí),reportError(..)函數(shù)也有一個(gè)JS異常會(huì)怎樣?會(huì)有人捕獲這個(gè)錯(cuò)誤嗎?沒(méi)有。
看!上面有一個(gè)隱含的Promise D,并且它會(huì)被告知reportError(..)內(nèi)部的異常。
OMG,你肯定會(huì)想。什么時(shí)候才能停止?它會(huì)這樣一直下去嗎?
一些promise庫(kù)作者認(rèn)為有必要解決這個(gè)問(wèn)題通過(guò)讓"安靜的錯(cuò)誤"被作為全局異常拋出。但是這種機(jī)制該如何得知你不想再鏈接promise并且提供一個(gè)錯(cuò)誤處理函數(shù)呢?它如何知道什么時(shí)候應(yīng)該通報(bào)一個(gè)全局異常或者不通報(bào)呢?你肯定不希望當(dāng)你已經(jīng)捕獲并且處理錯(cuò)誤的情況下仍然有很多控制臺(tái)錯(cuò)誤信息。
在某種意義上,你需要可以標(biāo)記一個(gè)promise為“final”,就像說(shuō)“這是我鏈子中的最后一個(gè)promise”或者“我不打算再鏈接了,所以這是烏龜停止的地方”。如果在鏈的最后發(fā)生了錯(cuò)誤并且沒(méi)有被捕獲,然后它需要被報(bào)告為一個(gè)全局異常。
從表面上我猜測(cè)這似乎是很明智的。這種情況下的實(shí)現(xiàn)像下面這樣:
var promiseC = promiseB.then( displayAnswer, reportError ); promiseC .catch( reportError ) .done(); // marking the end of the chain
你仍然需要記住調(diào)用done(),要不然錯(cuò)誤還是會(huì)隱藏在最后一個(gè)promsie中。你必須使用穩(wěn)固的錯(cuò)誤處理函數(shù)。
"惡心",你肯定會(huì)這么想。歡迎來(lái)到promises的歡樂(lè)世界。
對(duì)于錯(cuò)誤處理已經(jīng)說(shuō)了很多了。另一個(gè)核心promsie的限制是一個(gè)promise代表一個(gè)多帶帶的值。什么是一個(gè)多帶帶的值呢?它是一個(gè)對(duì)象或者一個(gè)數(shù)組或者一個(gè)字符串或者一個(gè)數(shù)字。等等,我還可以在一個(gè)容器里放入多個(gè)值,就像一個(gè)數(shù)組或?qū)ο笾械亩鄠€(gè)元素。Cool!
一個(gè)操作的最終結(jié)果不總是一個(gè)值,但是promise并不會(huì)這樣,這很微妙并且又是另一個(gè)失敗陷阱:
function ajax(url) { return new Promise( function(resolve,reject){ // make some ajax request // if you get a response, `resolve( answer, url )` // if it fails, `reject( excuses, url )` } ); } ajax( ".." ) .then( function(answer,url){ console.log( answer, url ); // .. undefined }, function(excuses,url){ console.log( excuses, url ); // .. undefined } );
你看出這里面的問(wèn)題了嗎?如果你意外的嘗試傳遞超過(guò)一個(gè)的值過(guò)去,不管傳給失敗處理函數(shù)還是成功處理函數(shù),只有第一個(gè)值能被傳遞過(guò)去,其他幾個(gè)會(huì)被默默地丟掉。
為什么?我相信這和組合的可預(yù)測(cè)性有關(guān),或者一些其他花哨的詞匯有關(guān)。最后,你不得不記住包裹自己的多個(gè)值要不然你就會(huì)不知不覺的丟失數(shù)據(jù)。
并行真實(shí)世界中的app經(jīng)常在“同一時(shí)間”發(fā)生超過(guò)一件事情。本質(zhì)上說(shuō),我們需要構(gòu)建一個(gè)處理器,并行處理多個(gè)事件,等待它們?nèi)客瓿稍賵?zhí)行回調(diào)函數(shù)。
相比于promise問(wèn)題,這是一個(gè)異步流程控制的問(wèn)題。一個(gè)多帶帶的promise不能表達(dá)兩個(gè)或更多并行發(fā)生的異步事件。你需要一個(gè)抽象層來(lái)處理它。
在計(jì)算機(jī)科學(xué)術(shù)語(yǔ)中,這個(gè)概念叫做一個(gè)“門”。一個(gè)等待所有任務(wù)完成,并且不關(guān)心它們完成順序的門。
在promise世界中,我們添加一個(gè)API叫做Promise.all(..),它可以構(gòu)建一個(gè)promise來(lái)等待所有傳遞進(jìn)來(lái)的promise完成。
Promise.all([ // these will all proceed "in parallel" makePromise1(), makePromise2(), makePromise3() ]) .then( .. );
一個(gè)相近的方法是race()。它的作用和all()一樣,除了它只要有一個(gè)promise返回消息就執(zhí)行回調(diào)函數(shù),而不等待其他promise的結(jié)果。
當(dāng)你思考這些方法的時(shí)候,你可能會(huì)想到許多方式來(lái)實(shí)現(xiàn)這些方法。Promise.all(..)和Promise.race(..)是原生提供的,因?yàn)檫@兩個(gè)方法是很常用到的,但是如果你還需要其他的功能那么你就需要一個(gè)庫(kù)來(lái)幫助你了。限制的另一個(gè)表現(xiàn)就是你很快就會(huì)發(fā)現(xiàn)你需要自己使用Array的相關(guān)方法來(lái)管理promise列表,比如.map(..)和.reduce(..)。如果你對(duì)map/reduce不熟悉,那么趕緊去熟悉一下,因?yàn)槟銜?huì)發(fā)現(xiàn)當(dāng)處理現(xiàn)實(shí)世界中promise的時(shí)候你經(jīng)常會(huì)需要它們。
幸運(yùn)的是,已經(jīng)有很多庫(kù)來(lái)幫助你了,并且每天還有很多新的庫(kù)被創(chuàng)造出來(lái)。
Single Shot Of Espresso,Please!另一個(gè)關(guān)于promise的事情是它們只會(huì)運(yùn)行一次,然后就不用了。
如果你只需要處理單個(gè)事件,比如初始化一個(gè)也沒(méi)或者資源加載,那么這樣沒(méi)什么問(wèn)題。但是如果你有一個(gè)重復(fù)的事件(比如用戶點(diǎn)擊按鈕),你每次都需要執(zhí)行一系列異步操作會(huì)怎么樣呢?Promise并不提供這樣的功能,因?yàn)樗鼈兪遣豢勺兊模簿褪遣荒鼙恢刂谩R貜?fù)同樣的promise,唯一的方法就是重新定義一個(gè)promise。
$("#my_button").click(function(evt){ doTask1( evt.target ) .then( doTask2 ) .then( doTask3 ) .catch( handleError ); });
太惡心了,不僅僅是因?yàn)橹貜?fù)創(chuàng)建promise對(duì)于效率有影響,而且它對(duì)于職責(zé)分散不利。你不得不把多個(gè)事件監(jiān)聽函數(shù)放在同一個(gè)函數(shù)中。如果有一個(gè)方式來(lái)改變這種情況就好了,這樣事件監(jiān)聽和事件處理函數(shù)就能夠分開了。
Microsoft的RxJS庫(kù)把這種方式叫做"觀察者模式"。我的asynquence庫(kù)有一個(gè)react(..)方法通過(guò)簡(jiǎn)單的方式提供了一個(gè)類似的功能。
盲區(qū)...在一個(gè)已經(jīng)被使用回調(diào)函數(shù)的API占據(jù)的世界中,把promise插入到代碼中比我們想象的要困難。考慮下面這段代碼:
function myAjax(url) { return new Promise( function(resolve,reject){ ajax( url, function(err,response){ if (err) { reject( err ); } else { resolve( response ); } } ) } ); }
我認(rèn)為promise解決了回調(diào)地獄的問(wèn)題,但是它們代碼看起來(lái)仍然像垃圾。我們需要抽象層來(lái)使得用promise表示回調(diào)變得更簡(jiǎn)單。原生的promise并沒(méi)有提供這個(gè)抽象層,所以結(jié)果就是通過(guò)原生promise寫出來(lái)的代碼還是很丑陋。但是如果有抽象層那么事情就變得很簡(jiǎn)單了。
例如,我的asynquence庫(kù)提供了一個(gè)errfcb()插件(error-first callback),用它可以構(gòu)建一個(gè)回調(diào)來(lái)處理下面這種場(chǎng)景:
function myAjax(url) { var sq = ASQ(); ajax( url, sq.errfcb() ); return sq; }Stop The Presses!
有時(shí),你想要取消一個(gè)promise而去做別的事情,但是如果現(xiàn)在你的promise正處在掛起狀態(tài)會(huì)怎樣呢?
var pr = ajax( ".." ) .then( transformResult ) .then( displayAnswer, reportError ); // Later pr.cancel(); // <-- doesn"t work!
所以,為了取消promise,你需要引入一下東西:
function transformResult(data) { if (!pr.ignored) { // do something! } } var pr = ajax( ".." ) .then( transformResult ) .then( displayAnswer, reportError ); // Later pr.ignored = true; // just hacking around
換句話說(shuō),你為了能夠取消你的promise,在promise上面加了一層來(lái)處理這種情況。你不能從promise取消注冊(cè)處理函數(shù)。并且因?yàn)橐粋€(gè)promise必須不可變,你能夠直接取消一個(gè)promise這種情況是不允許出現(xiàn)的。從外部取消一個(gè)promise跟改變它的狀態(tài)沒(méi)有什么區(qū)別。它使得promise變得不可靠。
許多promise庫(kù)都提供了這種功能,但是這明顯是一個(gè)錯(cuò)誤。取消這種行為是不需要promise,但是它可以出現(xiàn)在promise上面的一個(gè)抽象層里。
冗長(zhǎng)另一個(gè)關(guān)于原生promise的擔(dān)心是有些事情并沒(méi)有被實(shí)現(xiàn),所以你必須自動(dòng)手動(dòng)實(shí)現(xiàn)它們,而這些事情對(duì)于可擴(kuò)展性是很重要的,但是這些東西經(jīng)常會(huì)導(dǎo)致令人討厭的重復(fù)代碼。
看一個(gè)例子,在每一個(gè)promise的完成步驟中,有一個(gè)設(shè)定就是你希望保持鏈?zhǔn)浇Y(jié)構(gòu),所以then(..)方法會(huì)返回一個(gè)新的promise。但是如果你想要加入一個(gè)自己創(chuàng)建的promise并且從一個(gè)成功處理函數(shù)中返回,這樣你的promise就可以加入到鏈的流程控制中。
function transformResult(data) { // we have to manually create and return a promise here return new Promise( function(resolve,reject){ // whatever } ); } var pr = ajax( ".." ) .then( transformResult ) .then( displayAnswer, reportError );
不同的是,就像上面解釋的一樣,從第一個(gè)then(..)返回的隱藏的promise立刻就完成(或者失敗),然后你就沒(méi)辦法讓剩下的鏈異步延遲。如果有一個(gè)抽象層能夠通過(guò)某種方式把自動(dòng)創(chuàng)建/鏈接的promise暴露給你,然后你就不需要?jiǎng)?chuàng)建自己的promise來(lái)替換了,這樣該多好。
換句話說(shuō),如果有一個(gè)設(shè)定假設(shè)你需要為了異步的目的使用鏈,而不是你只是需要漂亮得執(zhí)行異步。(也就是說(shuō)你確實(shí)是希望你的代碼可以異步執(zhí)行,而不是說(shuō)希望整個(gè)異步流程看過(guò)去好看點(diǎn))。
另一個(gè)例子:你不能直接傳遞一個(gè)已經(jīng)存在的promise給then(..)方法,你必須傳遞一個(gè)返回這個(gè)promise的函數(shù)。
var pr = doTask2(); doTask1() .then( pr ); // would be nice, but doesn"t work! // instead: doTask1() .then( function(){ return pr; } );
這個(gè)限制性是有很多原因的。但是它只是減弱了有利于保持可擴(kuò)展性和可預(yù)測(cè)性的用法的簡(jiǎn)潔。抽象可以容易的解決這個(gè)問(wèn)題。
全劇終所有這些原因就是為什么原生的promise API是強(qiáng)大同時(shí)也是有局限性的。
關(guān)于擴(kuò)展和抽象是一個(gè)成熟的領(lǐng)域。許多庫(kù)正在做這些工作。就像我之前說(shuō)的,asynquence是我自己的promise抽象庫(kù)。它很小但是很強(qiáng)大。它解決了所有博客中提到的promise的問(wèn)題。
我后面會(huì)寫一篇詳細(xì)的博客來(lái)介紹asynquence是如果解決這些問(wèn)題的,所以敬請(qǐng)期待。
深入理解Promise五部曲--1.異步問(wèn)題
深入理解Promise五部曲--2.轉(zhuǎn)換問(wèn)題
深入理解Promise五部曲--3.可靠性問(wèn)題
深入理解Promise五部曲--4.擴(kuò)展性問(wèn)題
深入理解Promise五部曲--5.樂(lè)高問(wèn)題
最后,安利下我的個(gè)人博客,歡迎訪問(wèn):http://bin-playground.top
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/87598.html
摘要:當(dāng)引擎開始執(zhí)行一個(gè)函數(shù)比如回調(diào)函數(shù)時(shí),它就會(huì)把這個(gè)函數(shù)執(zhí)行完,也就是說(shuō)只有執(zhí)行完這段代碼才會(huì)繼續(xù)執(zhí)行后面的代碼。當(dāng)條件允許時(shí),回調(diào)函數(shù)就會(huì)被運(yùn)行。現(xiàn)在,返回去執(zhí)行注冊(cè)的那個(gè)回調(diào)函數(shù)。 原文地址:http://blog.getify.com/promis... 在微博上看到有人分享LabJS作者寫的關(guān)于Promise的博客,看了下覺得寫得很好,分五個(gè)部分講解了Promise的來(lái)龍去脈。從...
摘要:有一個(gè)和相關(guān)的更大的問(wèn)題。最后,請(qǐng)負(fù)有責(zé)任感并且使用安全的擴(kuò)展。深入理解五部曲異步問(wèn)題深入理解五部曲轉(zhuǎn)換問(wèn)題深入理解五部曲可靠性問(wèn)題深入理解五部曲擴(kuò)展性問(wèn)題深入理解五部曲樂(lè)高問(wèn)題最后,安利下我的個(gè)人博客,歡迎訪問(wèn) 原文地址:http://blog.getify.com/promis... 現(xiàn)在,我希望你已經(jīng)看過(guò)深入理解Promise的前三篇文章了。并且假設(shè)你已經(jīng)完全理解Promises...
摘要:只要在調(diào)用異步函數(shù)時(shí)設(shè)置一個(gè)或多個(gè)回調(diào)函數(shù),函數(shù)就會(huì)在完成時(shí)自動(dòng)調(diào)用回調(diào)函數(shù)。要解決的問(wèn)題是,如何將回調(diào)方法的參數(shù)從回調(diào)方法中傳遞出來(lái),讓它可以像同步函數(shù)的返回結(jié)果一樣,在回調(diào)函數(shù)以外的控制范圍內(nèi),可以傳遞和復(fù)用。 摘要: 我們知道 JavaScript 自從有了 Generator 之后,就有了各種基于 Generator 封裝的協(xié)程。其中 hprose 中封裝的 Promise 和...
摘要:直到最近,我們?nèi)匀辉谟煤?jiǎn)單的回調(diào)函數(shù)來(lái)處理異步的問(wèn)題。當(dāng)我們只有一個(gè)異步任務(wù)的時(shí)候使用回調(diào)函數(shù)看起來(lái)還不會(huì)有什么問(wèn)題。 原文地址:http://blog.getify.com/promis... 廈門旅行歸來(lái),繼續(xù)理解Promise 在上一篇深入理解Promise五部曲:1.異步問(wèn)題中,我們揭示了JS的異步事件輪詢并發(fā)模型并且解釋了多任務(wù)是如何相互穿插使得它們看起來(lái)像是同時(shí)運(yùn)行的。...
摘要:簡(jiǎn)單的說(shuō),即將到來(lái)的標(biāo)準(zhǔn)指出是一個(gè),所以作為一個(gè),必須可以被子類化。保護(hù)還是子類化這是個(gè)問(wèn)題我真的希望我能創(chuàng)建一個(gè)忠實(shí)的給及以下。 原文地址:http://blog.getify.com/promis... 如果你需要趕上我們關(guān)于Promise的進(jìn)度,可以看看這個(gè)系列前兩篇文章深入理解Promise五部曲--1.異步問(wèn)題和深入理解Promise五部曲--2.控制權(quán)轉(zhuǎn)移問(wèn)題。 Promi...
閱讀 1848·2021-11-22 15:24
閱讀 1307·2021-11-12 10:36
閱讀 3194·2021-09-28 09:36
閱讀 1837·2021-09-02 15:15
閱讀 2745·2019-08-30 15:54
閱讀 2391·2019-08-30 11:02
閱讀 2392·2019-08-29 13:52
閱讀 3539·2019-08-26 11:53