<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        詳細介紹JavaScript異步編程的Promise模式示例代碼

        來源:懂視網 責編:小采 時間:2020-11-27 20:24:16
        文檔

        詳細介紹JavaScript異步編程的Promise模式示例代碼

        詳細介紹JavaScript異步編程的Promise模式示例代碼:異步模式在web編程中變得越來越重要,對于web主流語言Javascript來說,這種模式實現起來不是很利索,為此,許多Javascript庫(比如 jQuery和Dojo)添加了一種稱為promise的抽象(有時也稱之為deferred)。通過這些庫,開發人員能夠在實際編程中使用 prom
        推薦度:
        導讀詳細介紹JavaScript異步編程的Promise模式示例代碼:異步模式在web編程中變得越來越重要,對于web主流語言Javascript來說,這種模式實現起來不是很利索,為此,許多Javascript庫(比如 jQuery和Dojo)添加了一種稱為promise的抽象(有時也稱之為deferred)。通過這些庫,開發人員能夠在實際編程中使用 prom
        異步模式在web編程中變得越來越重要,對于web主流語言Javascript來說,這種模式實現起來不是很利索,為此,許多Javascript庫(比如 jQuery和Dojo)添加了一種稱為promise的抽象(有時也稱之為deferred)。通過這些庫,開發人員能夠在實際編程中使用 promise模式。IE官方博客最近發表了一篇文章,詳細講述了如何使用XMLHttpRequest2來實踐promise模式。我們來了解一下相關的概念和應用。

        考慮這樣一個例子,某網頁存在異步操作(通過XMLHttpRequest2或者 Web Workers)。隨著Web 2.0技術的深入,瀏覽器端承受了越來越多的計算壓力,所以“并發”具有積極的意義。對于開發人員來說,既要保持頁面與用戶的交互不受影響,又要協調頁面與異步任務的關系,這種非線性執行的編程要求存在適應的困難。先拋開頁面交互不談,我們能夠想到對于異步調用需要處理兩種結果——成功操作和失敗處理。在成功的調用后,我們可能需要把返回的結果用在另一個Ajax請求中,這就會出現“函數連環套”的情況(在筆者的另一篇文章《NodeJS的異步編程風格》中有詳細的解釋)。這種情況會造成編程的復雜性。看看下面的代碼示例(基于XMLHttpRequest2):

        function searchTwitter(term, onload, onerror) {
        
         var xhr, results, url;
         url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;
         xhr = new XMLHttpRequest();
         xhr.open('GET', url, true);
        
         xhr.onload = function (e) {
         if (this.status === 200) {
         results = JSON.parse(this.responseText);
         onload(results);
         }
         };
        
         xhr.onerror = function (e) {
         onerror(e);
         };
        
         xhr.send();
         }
        
         function handleError(error) {
         /* handle the error */
         }
        
         function concatResults() {
         /* order tweets by date */
         }
        
         function loadTweets() {
         var container = document.getElementById('container');
        
         searchTwitter('#IE10', function (data1) {
         searchTwitter('#IE9', function (data2) {
         /* Reshuffle due to date */
         var totalResults = concatResults(data1.results, data2.results);
         totalResults.forEach(function (tweet) {
         var el = document.createElement('li');
         el.innerText = tweet.text;
         container.appendChild(el);
         });
         }, handleError);
         }, handleError);
         }

        上面的代碼其功能是獲取Twitter中hashtag為IE10和IE9的內容并在頁面中顯示出來。這種嵌套的回調函數難以理解,開發人員需要仔細分析哪些代碼用于應用的業務邏輯,而哪些代碼處理異步函數調用的,代碼結構支離破碎。錯誤處理也分解了,我們需要在各個地方檢測錯誤的發生并作出相應的處理。

        為了降低異步編程的復雜性,開發人員一直尋找簡便的方法來處理異步操作。其中一種處理模式稱為promise,它代表了一種可能會長時間運行而且不一定必須完整的操作的結果。這種模式不會阻塞和等待長時間的操作完成,而是返回一個代表了承諾的(promised)結果的對象。

        考慮這樣一個例子,頁面代碼需要訪問第三方的API,網絡延遲可能會造成響應時間較長,在這種情況下,采用異步編程不會影響整個頁面與用戶的交互。promise模式通常會實現一種稱為then的方法,用來注冊狀態變化時對應的回調函數。比如下面的代碼示例:

        searchTwitter(term).then(filterResults).then(displayResults);

        promise模式在任何時刻都處于以下三種狀態之一:未完成(unfulfilled)、已完成(resolved)和拒絕(rejected)。以CommonJS Promise/A 標準為例,promise對象上的then方法負責添加針對已完成和拒絕狀態下的處理函數。then方法會返回另一個promise對象,以便于形成promise管道,這種返回promise對象的方式能夠支持開發人員把異步操作串聯起來,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回調函數在promise對象進入完成狀態時會觸發,并傳遞結果;rejectedHandler函數會在拒絕狀態下調用。

        有了promise模式,我們可以重新實現上面的Twitter示例。為了更好的理解實現方法,我們嘗試著從零開始構建一個promise模式的框架。首先需要一些對象來存儲promise。

        var Promise = function () {
         /* initialize promise */
         };

        接下來,定義then方法,接受兩個參數用于處理完成和拒絕狀態。

        Promise.prototype.then = function (onResolved, onRejected) {
         /* invoke handlers based upon state transition */
         };

        同時還需要兩個方法來執行理從未完成到已完成和從未完成到拒絕的狀態轉變。

        Promise.prototype.resolve = function (value) {
         /* move from unfulfilled to resolved */
         };
        
         Promise.prototype.reject = function (error) {
         /* move from unfulfilled to rejected */
         };

        現在搭建了一個promise的架子,我們可以繼續上面的示例,假設只獲取IE10的內容。創建一個方法來發送Ajax請求并將其封裝在promise中。這個promise對象分別在xhr.onload和xhr.onerror中指定了完成和拒絕狀態的轉變過程,請注意searchTwitter函數返回的正是promise對象。然后,在loadTweets中,使用then方法設置完成和拒絕狀態對應的回調函數。

        function searchTwitter(term) {
        
         var url, xhr, results, promise;
         url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;
         promise = new Promise();
         xhr = new XMLHttpRequest();
         xhr.open('GET', url, true);
        
         xhr.onload = function (e) {
         if (this.status === 200) {
         results = JSON.parse(this.responseText);
         promise.resolve(results);
         }
         };
        
         xhr.onerror = function (e) {
         promise.reject(e);
         };
        
         xhr.send();
         return promise;
        }
        
        function loadTweets() {
         var container = document.getElementById('container');
         searchTwitter('#IE10').then(function (data) {
         data.results.forEach(function (tweet) {
         var el = document.createElement('li');
         el.innerText = tweet.text;
         container.appendChild(el);
         });
         }, handleError);
        }

        到目前為止,我們可以把promise模式應用于單個Ajax請求,似乎還體現不出promise的優勢來。下面來看看多個Ajax請求的并發協作。此時,我們需要另一個方法when來存儲準備調用的promise對象。一旦某個promise從未完成狀態轉化為完成或者拒絕狀態,then方法里對應的處理函數就會被調用。when方法在需要等待所有操作都完成的時候至關重要。

        Promise.when = function () {
         /* handle promises arguments and queue each */
        };

        以剛才獲取IE10和IE9兩塊內容的場景為例,我們可以這樣來寫代碼:

        var container, promise1, promise2;
        container = document.getElementById('container');
        promise1 = searchTwitter('#IE10');
        promise2 = searchTwitter('#IE9');
        Promise.when(promise1, promise2).then(function (data1, data2) {
        
         /* Reshuffle due to date */
         var totalResults = concatResults(data1.results, data2.results);
         totalResults.forEach(function (tweet) {
         var el = document.createElement('li');
         el.innerText = tweet.text;
         container.appendChild(el);
         });
        }, handleError);

        分析上面的代碼可知,when函數會等待兩個promise對象的狀態發生變化再做具體的處理。在實際的Promise庫中,when函數有很多變種,比如 when.some()、when.all()、when.any()等,讀者從函數名字中大概能猜出幾分意思來,詳細的說明可以參考CommonJS的一個promise實現when.js。

        除了CommonJS,其他主流的Javascript框架如jQuery、Dojo等都存在自己的promise實現。開發人員應該好好利用這種模式來降低異步編程的復雜性。我們選取Dojo為例,看一看它的實現有什么異同。

        Dojo框架里實現promise模式的對象是Deferred,該對象也有then函數用于處理完成和拒絕狀態并支持串聯,同時還有resolve和reject,功能如之前所述。下面的代碼完成了Twitter的場景:

        function searchTwitter(term) {
        
         var url, xhr, results, def;
         url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;
         def = new dojo.Deferred();
         xhr = new XMLHttpRequest();
         xhr.open('GET', url, true);
        
         xhr.onload = function (e) {
         if (this.status === 200) {
         results = JSON.parse(this.responseText);
         def.resolve(results);
         }
         };
        
         xhr.onerror = function (e) {
         def.reject(e);
         };
        
         xhr.send();
         return def;
        }
        
        dojo.ready(function () {
         var container = dojo.byId('container');
         searchTwitter('#IE10').then(function (data) {
         data.results.forEach(function (tweet) {
         dojo.create('li', {
         innerHTML: tweet.text
         }, container);
         });
         });
        });

        不僅如此,類似dojo.xhrGet方法返回的即是dojo.Deferred對象,所以無須自己包裝promise模式。

        var deferred = dojo.xhrGet({
         url: "search.json",
         handleAs: "json"
        });
        
        deferred.then(function (data) {
         /* handle results */
        }, function (error) {
         /* handle error */
        });

        除此之外,Dojo還引入了dojo.DeferredList,支持開發人員同時處理多個dojo.Deferred對象,這其實就是上面所提到的when方法的另一種表現形式。

        dojo.require("dojo.DeferredList");
        dojo.ready(function () {
         var container, def1, def2, defs;
         container = dojo.byId('container');
         def1 = searchTwitter('#IE10');
         def2 = searchTwitter('#IE9');
        
         defs = new dojo.DeferredList([def1, def2]);
        
         defs.then(function (data) {
         // Handle exceptions
         if (!results[0][0] || !results[1][0]) {
         dojo.create("li", {
         innerHTML: 'an error occurred'
         }, container);
         return;
         }
         var totalResults = concatResults(data[0][1].results, data[1][1].results);
        
         totalResults.forEach(function (tweet) {
         dojo.create("li", {
         innerHTML: tweet.text
         }, container);
         });
         });
        });

        上面的代碼比較清楚,不再詳述。

        說到這里,讀者可能已經對promise模式有了一個比較完整的了解,異步編程會變得越來越重要,在這種情況下,我們需要找到辦法來降低復雜度,promise模式就是一個很好的例子,它的風格比較人性化,而且主流的JS框架提供了自己的實現。所以在編程實踐中,開發人員應該嘗試這種便捷的編程技巧。需要注意的是,promise模式的使用需要恰當地設置promise對象,在對應的事件中調用狀態轉換函數,并且在最后返回promise對象。

        技術社區對異步編程的關注也在升溫,國內社區也發出了自己的聲音。資深技術專家老趙就發布了一套開源的異步開發輔助庫Jscex,它的設計很巧妙,拋棄了回調函數的編程方式,采用一種“線性編碼、異步執行”的思想,感興趣的讀者可以查看這里。

        不僅僅是前端的JS庫,如今火熱的NodeJS平臺也出現了許多第三方的promise模塊,具體的清單可以訪問這里。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        詳細介紹JavaScript異步編程的Promise模式示例代碼

        詳細介紹JavaScript異步編程的Promise模式示例代碼:異步模式在web編程中變得越來越重要,對于web主流語言Javascript來說,這種模式實現起來不是很利索,為此,許多Javascript庫(比如 jQuery和Dojo)添加了一種稱為promise的抽象(有時也稱之為deferred)。通過這些庫,開發人員能夠在實際編程中使用 prom
        推薦度:
        標簽: 模式 js 代碼
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 91频在线观看免费大全| 在线看片免费人成视频播| 青苹果乐园免费高清在线| 亚洲国产成人久久77| 久久精品国产免费观看三人同眠| 亚洲国产女人aaa毛片在线| 久久久久久久99精品免费| 无码乱人伦一区二区亚洲| 三年片在线观看免费观看大全一| 亚洲国产人成网站在线电影动漫| 免费A级毛片av无码| 亚洲av午夜精品无码专区| 久久久久国产精品免费免费搜索| 亚洲人成欧美中文字幕| 日批日出水久久亚洲精品tv| 亚洲精品国产日韩无码AV永久免费网| 91麻豆国产自产在线观看亚洲| 青青操在线免费观看| 亚洲精品偷拍无码不卡av| 男女免费观看在线爽爽爽视频 | 久章草在线精品视频免费观看| 亚洲AV无码成人精品区在线观看| 久久青草免费91线频观看站街| 亚洲欧洲日产国码二区首页| 好男人www免费高清视频在线| 成人婷婷网色偷偷亚洲男人的天堂| 亚洲成a人片在线播放| 午夜网站在线观看免费完整高清观看| 亚洲福利视频网址| 免费午夜爽爽爽WWW视频十八禁| 99re8这里有精品热视频免费| 亚洲黄色网址大全| 国产乱子影视频上线免费观看| 成人自慰女黄网站免费大全| 亚洲喷奶水中文字幕电影| 亚洲成人一区二区| 国产成人精品免费视频动漫| 免费精品国自产拍在线播放 | 亚洲va久久久噜噜噜久久男同 | 国产人在线成免费视频| 又黄又大的激情视频在线观看免费视频社区在线|