摘要:可信任性確定性在解決上述的回調函數的問題之前,有必要先來認識一下的一些主要方法的起點執行結果依次是,,,代碼解讀以上代碼體現了的如下特性一旦決議調用過一次或者就不再重復調用決議回調或者改變決議回調。
通過回調來理解Promise
我們都知道Promise的出現是為了規避回調地獄的,由此,我們先來深入了解一下回調的缺陷:
回調1、缺乏信任
2、不確定性
Example
var money = 30; order(money,function getOrder(orderId){ // order是一個第三方的下訂單的回調函數 orderId && pay(orderId); // 獲取訂單編號之后調用第三方支付pay方法去付款 }) // ...同步代碼
代碼解讀:上面的代碼只是常規代碼中的一部分,其中order是一個第三方下訂單的方法,需要攜帶回調函數過去獲取訂單編號,這里面就存在一些信任性和不確定性的問題,如:
1、有可能回調函數getOrder始終不會被調用,那我們就永遠拿不到訂單編號去支付;
2、有可能回調了,可是回調了不止一次,導致我們重復去支付了;
3、不確定回掉時間,有可能立馬回調,那么接下來的同步代碼就會在回調之后執行,有可能它內部調用了異步代碼再回調,那么接下來的同步代碼就會在回調之前執行。
4、也有可能下訂單的第三方模塊自己內部出錯了,導致我們沒辦法捕獲異常;
上面只是回調的一部分缺陷,但其實當我們不喜歡一個東西的時候總有這么多理由,當我們喜歡一個東西的時候,沒有理由也會找一堆理由的,下面就是Promise的理由。
Promise1、可信任性
2、確定性
在解決上述的回調函數的問題之前,有必要先來認識一下Promise的一些主要方法:
1、Promise的起點new Promise()Example
console.log(1); let promise = new Promise(function PromiseBack(resolve,reject){ resolve(); resolve(); reject(); reject(); console.log(2); }).then(()=>{ console.log(4); },()=>{ console.log(5); }) console.log(3); // 執行結果依次是:1,2,3,4
代碼解讀:以上代碼體現了new Promise的如下特性:
2、多Promise同時執行:Promise.all([ .. ])1、一旦決議(調用過一次resolve或者reject)就不再重復調用決議回調或者改變決議回調。
2、決議代碼是同步的,可是決議的成功或失敗的回調代碼一定是異步的,而且Promise的異步實現比setTimeout的調用時間更早,因為回調決議存在于Event loop的microtask隊列中。
Example
let promise1 = new Promise(function(resolve,reject){ resolve(1); }); let promise2 = new Promise(function(resolve,reject){ resolve(2); // reject(3); }); let promise3 = Promise.all([promise1,promise2]).then(function resolveBack(result){ console.log(result); // 打印結果是:[ 1, 2 ] },function rejectBack(result){ console.log(result); // 當promise2注釋部分放開,非注釋部分注釋,打印結果是:3 })
代碼解讀:Promise.all方法對于promise數組的決議是:當其中所有的promise都是成功決議的時候,就會調用成功的決議回調resolveBack,并且把promise數組的決議值以數組的形式按照順序返回resolve中的值;如果其中哪怕有一個失敗的決議都會調用失敗的決議回調rejectBack,并且只返回promise宿主中失敗的決議值,以數組順序返回。
3、多Promise競賽執行:Promise.race([ .. ])Example
let promise1 = new Promise(function(resolve,reject){ setTimeout(function(){ resolve(1); },100); }); let promise2 = new Promise(function(resolve,reject){ setTimeout(function(){ //resolve(2); reject(3); },50); }); let promise3 = Promise.race([promise1,promise2]).then(function resolveBack(result){ console.log(result); // 打印結果是:2 },function rejectBack(result){ console.log(result); // 當promise2注釋部分放開,非注釋部分注釋,打印結果是:3 })
代碼解讀:Promise.race方法和all方法不同,它對于promise數組的決議是:當promise數組中有一個成功了,那就會立即執行成功的決議回調,當有一個失敗了,就會立即執行失敗的決議回調,所以,它也叫競賽決議,它的一個常用的應用場景就是異步請求超時處理,代碼如下:
Example:
// request(..)是一個支持Promise的Ajax工具 let promise1 = request( "http://some.url.1/"); let promise2 = function(second=1000){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ reject("請求超時"); },second) }) }; let promise3 = Promise.race([promise1,promise2(3000)]) .then(function resolveBack(result){ console.log(result); },function rejectBack(result){ console.log(result); // 當請求超時3秒鐘就決議失敗,打印錯誤信息,如果這里信息是統一處理,那最好超時的值構造成和異步請求返回錯誤結果的值一致 })4、Promise錯誤處理catch...
Example
new Promise((resolve,reject)=>{ console.log(a); }).catch((err)=>{ console.log(err); // 打印結果:33 [ReferenceError: a is not defined] })
代碼解讀:catch和then一樣都是Promise的實例方法,而且也都調用完成之后也都會返回一個新的Promise實例,這樣就可以繼續then或catch了,這也就是Promise的“鏈式流”。其實catch本身實現和then是類似的,可以完全看成是then僅有失敗決議回調,即:then(null,(err)=>{})。也就是說then的失敗決議當Promise決議代碼出錯了,哪怕沒有調用reject方法,也是會被捕獲到錯誤的。
總結瀏覽過上述方法之后,我們現在來解決一開始我們遇到的那個回調函數的問題,解決問題代碼如下:
Example
var money = 30; let promise1 = new Promise(function(resolve,reject){ order(money,function getOrder(orderId){ orderId ? resolve(orderId) : reject(orderId); }); }); let promise2 = function(second=1000){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ reject("請求超時"); },second) }) }; let promise3 = Promise.race([promise1,promise2(3000)]) .then(function resolveBack(result){ console.log(result); },function rejectBack(result){ console.log(result); // 當請求超時,或者order內部代碼錯誤等都會調用失敗的決議 }) // ...同步代碼
代碼解讀:上面這個Promise例子展示了對回調問題的規避,具體解決思路是:
1、通過使用Promise.race競賽決議方法解決如果第三方的order方法不調用getOrder的情況,可以定位到具體的錯誤代碼和錯誤原因;
2、根據Promise的決議特性:一旦決議不可狀態不可更改,不可重復。解決了回調了不止一次的問題;
3、根據Promise的決議回調是異步的特性,決議的回調一定是異步的特性,解決了回調時間的不確定性。
4、根據rejectBack類似catch的特性,失敗的決議回調是可以捕獲到決議代碼異常的報錯的,那這樣,如果第三方內部出現了問題,是可以捕獲到的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84610.html
摘要:直到最近,我們仍然在用簡單的回調函數來處理異步的問題。當我們只有一個異步任務的時候使用回調函數看起來還不會有什么問題。 原文地址:http://blog.getify.com/promis... 廈門旅行歸來,繼續理解Promise 在上一篇深入理解Promise五部曲:1.異步問題中,我們揭示了JS的異步事件輪詢并發模型并且解釋了多任務是如何相互穿插使得它們看起來像是同時運行的。...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:理解回調和原文自工程師博客,傳送門這兩個概念是編程語言的基本內容。回調地獄就是濫用回調。通常,在回調中,錯誤作為第一個參數傳遞。這個具有這兩個函數作為參數的回調稱為執行程序。到目前為止,我希望我已經讓自己了解了回調和。 理解回調和Promise 原文自工程師Fernando Hernandez博客,傳送門 這兩個概念是Javascript編程語言的基本內容。因為這種語言是在異步編程的...
摘要:從源碼看概念與實現是異步編程中的重要概念,它較好地解決了異步任務中回調嵌套的問題。這些概念中有趣的地方在于,標識狀態的變量如都是形容詞,用于傳入數據的接口如與都是動詞,而用于傳入回調函數的接口如及則在語義上用于修飾動詞的副詞。 從源碼看 Promise 概念與實現 Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務中回調嵌套的問題。在沒有引入新的語言機制的前提下,這...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規范并可配合使用的寫一個符合規范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環代替(異步)遞歸 問題描述 在開發過程中,遇到一個需求:在系統初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
閱讀 3768·2023-04-25 21:09
閱讀 3128·2021-10-20 13:48
閱讀 2942·2021-09-24 10:25
閱讀 2931·2021-08-21 14:08
閱讀 1790·2019-08-30 15:56
閱讀 976·2019-08-30 15:52
閱讀 1841·2019-08-29 14:11
閱讀 3562·2019-08-29 11:01