js 异步编程风格
promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。
promise.then(resolvedHandler, rejectedHandler)//针对已完成和拒绝状态的处理,可以在resolvedHandler方法中返回自己的promise组成级联 then().then(), 如果没有自己的promise则then()返回原始的promise
promise 状态只能改变一次unfulfilled>resolved or unfulfilled>rejected,状态改变后执行对应的回调,若在添加回调时状态已经改变则回调立即执行。
原始回调
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);
}
promise方式
var Promise = function () {
/* initialize 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 */
};
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原理
var defer = function () {
var pending = [], value;
return {
resolve: function (_value) {
value = _value;
for (var i = 0, ii = pending.length; i < ii; i++) {
var callback = pending[i];
callback(value);
}
pending = undefined;
},
then: function (callback) {
if (pending) {
pending.push(callback);
} else {
callback(value);
}
}
}
};
reference:
http://acgtofe.com/posts/2015/03/promise-from-zero/
http://www.infoq.com/cn/news/2011/09/js-promise/