Javascript Promise 学习 (中)
时隔多日,对promise有了多一点点的了解。
最近用angularjs 做开发,所以研究了一下它的 $q
功能不算很强大,算是简化版的 Q.js
参考了一下源码,不过我的等级还差很多...
作为学习,我自己又重写了一篇。
这次的比较整齐。代码也少了 .
$q = function (asyncFn) { var defer = new Deferred(); asyncFn(defer.resolve.bind(defer), defer.reject.bind(defer)); return defer.promise; }; $q.defer = function () { return new Deferred(); }; $q.reject = function (reason) { var defer = new Deferred(); defer.reject(reason); return defer.promise; }; $q.all = function (values) { var defer = new Deferred(); var finalDatas = []; var count = 0; values.forEach(function (value, i) { count++; $q.when(value, function (data) { finalDatas[i] = data; //直接按index装入,不用另外排序 if (--count === 0) { //一个++ 一个-- 互相抵消 defer.resolve(finalDatas); } }, function (reason) { defer.reject(reason); }); }); return defer.promise; }; $q.when = function (value, onFulfilled, onRejected, onNotify) { if (value instanceof Promise) return value.then(onFulfilled, onRejected, onNotify); var defer = new Deferred(); defer.resolve(value); return defer.promise.then(onFulfilled, onRejected, onNotify); }; function Deferred() { this.promise = new Promise(); } Deferred.prototype = { //resolve reject 几乎是一样的, notify 在调用后不会被删除 resolve: function (data) { var promise = this.promise; //要延误执行,防止then方法还没有设置好回调,就想要resolve的情况 setTimeout(function () { promise.states = "fulfilled"; promise._processCallback(data); }, 0); }, reject: function (reason) { var promise = this.promise; setTimeout(function () { promise.states = "rejected"; promise._processCallback(reason); }, 0); }, notify: function (data) { var promise = this.promise; setTimeout(function () { promise.states = "notify"; promise._processCallback(data, true); }, 0); }, constructor: Deferred } //主要是保存defer, 做promise连用 function Callback(defer, onFulfilled, onRejected, onNotify) { this.defer = defer; this.onFulfilled = onFulfilled; this.onRejected = onRejected; this.onNotify = onNotify; } function Promise() { this.states = "pending"; this.value = undefined; this.reason = undefined; this._callbacks = []; } Promise.prototype = { then: function (onFulfilled, onRejected, onNotify) { //把回调收集起来,如果states不是等待就马上出发 var defer = new Deferred(); this._callbacks.push(new Callback(defer, onFulfilled, onRejected, onNotify)); if (this.states !== "pending") { var data = (this.states === "fulfilled") ? this.value : this.reason; this._processCallback(data); } return defer.promise; }, "catch": function (onRejected) { return this.then(null, onRejected); }, 'finally': function (cleanup) { return this.then(cleanup, cleanup); }, _processCallback: function (data, is_keepCallback) { //这里的data不接受promise,偷懒没做。哈哈 var promise = this; if (this.states === "pending") return; var states = ("on-" + this.states).toCamelCase(); var promiseCallbacks = this._callbacks; var length = promiseCallbacks.length; for (var i = 0, l = promiseCallbacks.length; i < l; i++) { var callback = (is_keepCallback) ? promiseCallbacks[i] : promiseCallbacks.shift(); var defer = callback.defer; if (G.isFunction(callback[states])) { //要做错误处理哦 try { //调用回调, var returnValue = callback[states](data); //如果是promise那就乾坤大挪移把promise连连接过去 if (returnValue instanceof Promise) { returnValue.then(defer.resolve.bind(defer), defer.reject.bind(defer));//这里要用bind,因为resolve内需要引用this } else { //不是的话就到值传给下一个promise咯 defer.resolve(returnValue); } } catch (e) { defer.reject(e); } } else { //data不是函数就直接传下去 defer.resolve(data); } } }, constructor: Promise }