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/