摘要:我們可以進行適當的改進,把回調函數寫到外面即使是改寫成這樣,代碼還是不夠直觀,但是如果有了對象,代碼就可以寫得非常清晰,一目了然,請看這樣函數就不用寫在的回調中了目前的標準中還未支持對象,那么我們就自己動手,豐衣足食吧。
本文同步自我得博客:http://www.joeray61.com
很多做前端的朋友應該都聽說過Promise(或者Deferred)對象,今天我就講一下我對Promise的認識
What?Promise是CommonJS的規范之一,擁有resolve、reject、done、fail、then等方法,能夠幫助我們控制代碼的流程,避免函數的多層嵌套。如今異步在web開發中越來越重要,對于開發人員來說,這種非線性執行的編程會讓開發者覺得難以掌控,而Promise可以讓我們更好地掌控代碼的執行流程,jQuery等流行的js庫都已經實現了這個對象,年底即將發布的ES6也將原生實現Promise
Why想象這樣一個場景,兩個異步請求,第二個需要用到第一個請求成功的數據,那么我們代碼可以這樣寫
ajax({ url: url1, success: function(data) { ajax({ url: url2, data: data, success: function() { } }); } });
如果繼續下去在回調函數中進行下一步操作,嵌套的層數會越來越多。我們可以進行適當的改進,把回調函數寫到外面
function A() { ajax({ url: url1, success: function(data) { B(data); } }); } function B(data) { ajax({ url: url2, success: function(data) { ...... } }); }
即使是改寫成這樣,代碼還是不夠直觀,但是如果有了Promise對象,代碼就可以寫得非常清晰,一目了然,請看
new Promise(A).done(B);
這樣函數B就不用寫在A的回調中了
How目前的ES標準中還未支持Promise對象,那么我們就自己動手,豐衣足食吧。思路大致是這樣的,用2個數組(doneList和failList)分別存儲成功時的回調函數隊列和失敗時的回調隊列
state: 當前執行狀態,有pending、resolved、rejected3種取值
done: 向doneList中添加一個成功回調函數
fail: 向failList中添加一個失敗回調函數
then: 分別向doneList和failList中添加回調函數
always: 添加一個無論成功還是失敗都會調用的回調函數
resolve: 將狀態更改為resolved,并觸發綁定的所有成功的回調函數
reject: 將狀態更改為rejected,并觸發綁定的所有失敗的回調函數
when: 參數是多個異步或者延遲函數,返回值是一個Promise兌現,當所有函數都執行成功的時候執行該對象的resolve方法,反之執行該對象的reject方法
下面是我的具體實現過程:
var Promise = function() { this.doneList = []; this.failList = []; this.state = "pending"; }; Promise.prototype = { constructor: "Promise", resolve: function() { this.state = "resolved"; var list = this.doneList; for(var i = 0, len = list.length; i < len; i++) { list[0].call(this); list.shift(); } }, reject: function() { this.state = "rejected"; var list = this.failList; for(var i = 0, len = list.length; i < len; i++){ list[0].call(this); list.shift(); } }, done: function(func) { if(typeof func === "function") { this.doneList.push(func); } return this; }, fail: function(func) { if(typeof func === "function") { this.failList.push(func); } return this; }, then: function(doneFn, failFn) { this.done(doneFn).fail(failFn); return this; }, always: function(fn) { this.done(fn).fail(fn); return this; } }; function when() { var p = new Promise(); var success = true; var len = arguments.length; for(var i = 0; i < len; i++) { if(!(arguments[i] instanceof Promise)) { return false; } else { arguments[i].always(function() { if(this.state != "resolved"){ success = false; } len--; if(len == 0) { success ? p.resolve() : p.reject(); } }); } } return p; }Improve
目前只是實現了Promise的基礎功能,但仍然還有無法處理的情況,例如要實現3個或3個以上的異步請求的串行,目前我的Promise沒有辦法支持new Promise(A).then(B).then(C)這樣的形式,jQuery在1.7的版本中為Deferred(Promise)對象實現了pipe函數,可以通過這個函數實現上述功能,代碼為$.Deferred(A).pipe(B).then(C),我嘗試去讀了jQuery這部分的代碼,但是沒能讀懂,希望有大神能夠給一些實現思路
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85282.html
摘要:事件循環背景是一門單線程非阻塞的腳本語言,單線程意味著,代碼在執行的任何時候,都只有一個主線程來處理所有的任務。在意識到該問題之際,新特性中的可以讓成為一門多線程語言,但實際開發中使用存在著諸多限制。這個地方被稱為執行棧。 事件循環(Event Loop) 背景 JavaScript是一門單線程非阻塞的腳本語言,單線程意味著,JavaScript代碼在執行的任何時候,都只有一個主線程來...
摘要:如果有錯誤,則到的第二個回調函數中,對錯誤進行處理。假設第一個的第一個回調沒有返回一個對象,那么第二個的調用者還是原來的對象,只不過其的值變成了第一個中第一個回調函數的返回值。 ES6標準出爐之前,一個幽靈,回調的幽靈,游蕩在JavaScript世界。 正所謂: 世界本沒有回調,寫的人多了,也就有了})})})})})。 Promise的興起,是因為異步方法調用中,往往會出現回調函數一...
摘要:在語言中,函數替換的不是表達式,而是多參數函數,將其替換成一個只接受回調函數作為參數的單參數函數。為什么里面必須使用函數呢,因為我們需要確保傳入的值只有一個,利用其回調函數,來進行遞歸自動控制函數的流程,接收和交還程序的執行權 前言 這篇文章主要是梳理一下自己對阮一峰大神寫的關于async/await文章,有寫得不對的地方以及理解得不對的地方,各位大佬請指錯! 對比 簡單對比傳統異步,...
摘要:如果沒有其他異步任務要處理比如到期的定時器,會一直停留在這個階段,等待請求返回結果。執行的執行事件關閉請求的,例如事件循環的每一次循環都需要依次經過上述的階段。因此,才會早于執行。 showImg(https://segmentfault.com/img/bVbnY76); 概念 同步任務(Synchronous) 在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行后一個任務 ...
摘要:三即生成器,它是生成器函數返回的一個對象,是中提供的一種異步編程解決方案而生成器函數有兩個特征,一是函數名前帶星號,二是內部執行語句前有關鍵字調用一個生成器函數并不會馬上執行它里面的語句,而是返回一個這個生成器的迭代器對象。 文章來自微信公眾號:前端工坊(fe_workshop),不定期更新有趣、好玩的前端相關原創技術文章。 如果喜歡,請關注公眾號:前端工坊版權歸微信公眾號所有,轉載請...
閱讀 2335·2023-04-25 14:29
閱讀 1457·2021-11-22 09:34
閱讀 2702·2021-11-22 09:34
閱讀 3392·2021-11-11 10:59
閱讀 1851·2021-09-26 09:46
閱讀 2223·2021-09-22 16:03
閱讀 1921·2019-08-30 12:56
閱讀 479·2019-08-30 11:12