javascript
JavaScript中使Promise模式进行异步编程
Promises
其中的一種模式就是promise,它代表了一種潛在地、長時間運行但不必返回完成操作的結果。與阻塞并長時間等待運行計算完成不同,這種模式返回一個代表承諾(promised)結果的對象。
例如,需要創建一個請求到第三方系統,而它的網絡延遲是不確定的。應用程序可以被釋放出來做其他事情,直到這個請求返回值需要使用到,而不是在等待并阻塞住整個程序。Pormise實現了一種方法,即為狀態的變化注冊相應的回調函數,通常命名為then方法。
var results = searchTwitter(term).then(filterResults); displayResults(results);在任何時刻,promise只可能處于三種狀態之一:unfulfilled(未完成), resolved(已解決) or rejected(拒絕)。
為了說明這些概念是如何工作的,我們可以了解下CommonJS Promise/A標準,這個標準在流行的庫中已經有了許多衍生工具。在promise對象中的then方法為resolved以及rejected狀態添加了處理程序。then函數會返回另外一個promise對象以便形成promise管道,使開發人員能夠將異步操作串聯起來,這樣第一個操作的結果就可以作為參數傳入到第二個中了。
then(resolvedHandler, rejectedHandler);函數resolvedHandler回調函數會在promise對象進入完成狀態時調用,并傳遞計算(computation)出來的結果。而rejectedHandler函數會在promise對象進入拒絕狀態時被調用。
可以用promise的偽代碼來重現上面的示例,主要包含創建一個Ajax請求用于搜索Twitter、用數據填充屏幕以及處理錯誤。為了更好的理解實現方法,我們嘗試著從零開始構建一個promise模式的框架。我們以一個例子開始,即如果我們從頭開始設計一個僅包含基礎功能的promise庫應該有什么,首先,我們需要一些對象格式來保存promise。
var Promise = function () {/* initialize promise */ };接下來,我們需要實現then方法,允許我們根據promise的狀態變化將操作串聯在一起。這個方法包含兩個函數參數,用于處理promise被解決以及promise被拒絕的情況。
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標簽的tweets。首先,我們通過使用XMLHttpRequest2創建一個方法來發送一個Ajax Get請求到一個給定的URL,并且將它封裝成一個promise。接下來,我們將特別為Twitter創建一個方法,用來調用含有給定搜索條件的Ajax封裝方法。最后,我們會調用我們的搜索函數并在無序列表中展示結果。
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請求,那么接下來討論另一種場景——我們想要發送超過一個Ajax請求并協調它們的結果。為了處理這種場景,我們會在我們的Promise對象中創造一個when方法,用來儲存被調用的promise對象。一旦promise從unfulfilled轉變成resolved或者rejected,then方法里對應的處理函數就會被調用。有個場景至關重要,即when方法需要等待所有操作都完成才能繼續。
Promise.when = function () {/* handle promises arguments and queue each */ };現在我們可以同時存儲多個promise,以在Twitter上搜索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);要重點記住的是,在這些例子中的代碼除了普通JavaScript代碼,并沒有其它特別的。Web開發人員必定會創造他們自己的類Promise庫;但為了方便和一致性,你可以利用在一般JavaScript庫中公開的promise模式。
?
原文:
https://github.com/pingan1927/translate/blob/master/Asynchronous%20Programming%20in%20JavaScript%20with%20%E2%80%9CPromises%E2%80%9D.md
JQuery AJAX?deferred :
?http://api.jquery.com/category/deferred-object/
總結
以上是生活随笔為你收集整理的JavaScript中使Promise模式进行异步编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MFC的Button和Static控件
- 下一篇: javascript理论篇(详情见地址)