javascript
JavaScript中使Promise模式进行异步编程
Promises
其中的一種模式就是promise,它代表了一種潛在地、長時間運行但不必返回完成操作的結(jié)果。與阻塞并長時間等待運行計算完成不同,這種模式返回一個代表承諾(promised)結(jié)果的對象。
例如,需要創(chuàng)建一個請求到第三方系統(tǒng),而它的網(wǎng)絡(luò)延遲是不確定的。應(yīng)用程序可以被釋放出來做其他事情,直到這個請求返回值需要使用到,而不是在等待并阻塞住整個程序。Pormise實現(xiàn)了一種方法,即為狀態(tài)的變化注冊相應(yīng)的回調(diào)函數(shù),通常命名為then方法。
var results = searchTwitter(term).then(filterResults); displayResults(results);在任何時刻,promise只可能處于三種狀態(tài)之一:unfulfilled(未完成), resolved(已解決) or rejected(拒絕)。
為了說明這些概念是如何工作的,我們可以了解下CommonJS Promise/A標(biāo)準(zhǔn),這個標(biāo)準(zhǔn)在流行的庫中已經(jīng)有了許多衍生工具。在promise對象中的then方法為resolved以及rejected狀態(tài)添加了處理程序。then函數(shù)會返回另外一個promise對象以便形成promise管道,使開發(fā)人員能夠?qū)惒讲僮鞔?lián)起來,這樣第一個操作的結(jié)果就可以作為參數(shù)傳入到第二個中了。
then(resolvedHandler, rejectedHandler);函數(shù)resolvedHandler回調(diào)函數(shù)會在promise對象進入完成狀態(tài)時調(diào)用,并傳遞計算(computation)出來的結(jié)果。而rejectedHandler函數(shù)會在promise對象進入拒絕狀態(tài)時被調(diào)用。
可以用promise的偽代碼來重現(xiàn)上面的示例,主要包含創(chuàng)建一個Ajax請求用于搜索Twitter、用數(shù)據(jù)填充屏幕以及處理錯誤。為了更好的理解實現(xiàn)方法,我們嘗試著從零開始構(gòu)建一個promise模式的框架。我們以一個例子開始,即如果我們從頭開始設(shè)計一個僅包含基礎(chǔ)功能的promise庫應(yīng)該有什么,首先,我們需要一些對象格式來保存promise。
var Promise = function () {/* initialize promise */ };接下來,我們需要實現(xiàn)then方法,允許我們根據(jù)promise的狀態(tài)變化將操作串聯(lián)在一起。這個方法包含兩個函數(shù)參數(shù),用于處理promise被解決以及promise被拒絕的情況。
Promise.prototype.then = function (onResolved, onRejected) {/* invoke handlers based upon state transition */ };我們也需要一對方法來處理未完成和已解決或者未完成和已拒絕之間的狀態(tài)轉(zhuǎn)換。
Promise.prototype.resolve = function (value) {/* move from unfulfilled to resolved */ };Promise.prototype.reject = function (error) {/* move from unfulfilled to rejected */ };對于一個promise對于應(yīng)該是什么樣,現(xiàn)在我們已經(jīng)搭建的差不多了。我們可以繼續(xù)上面的示例,獲取包含IE10標(biāo)簽的tweets。首先,我們通過使用XMLHttpRequest2創(chuàng)建一個方法來發(fā)送一個Ajax Get請求到一個給定的URL,并且將它封裝成一個promise。接下來,我們將特別為Twitter創(chuàng)建一個方法,用來調(diào)用含有給定搜索條件的Ajax封裝方法。最后,我們會調(diào)用我們的搜索函數(shù)并在無序列表中展示結(jié)果。
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模式應(yīng)用于單個Ajax請求,那么接下來討論另一種場景——我們想要發(fā)送超過一個Ajax請求并協(xié)調(diào)它們的結(jié)果。為了處理這種場景,我們會在我們的Promise對象中創(chuàng)造一個when方法,用來儲存被調(diào)用的promise對象。一旦promise從unfulfilled轉(zhuǎn)變成resolved或者rejected,then方法里對應(yīng)的處理函數(shù)就會被調(diào)用。有個場景至關(guān)重要,即when方法需要等待所有操作都完成才能繼續(xù)。
Promise.when = function () {/* handle promises arguments and queue each */ };現(xiàn)在我們可以同時存儲多個promise,以在Twitter上搜索IE10和IE9兩個標(biāo)簽的內(nèi)容為例。
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開發(fā)人員必定會創(chuàng)造他們自己的類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/
總結(jié)
以上是生活随笔為你收集整理的JavaScript中使Promise模式进行异步编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MFC的Button和Static控件
- 下一篇: c3po 问题解决