/** * * @authors yutent (yutent@doui.cc) * @date 2016-11-26 16:35:45 * */ var _Promise = function(callback) { this.callback = [] var _this = this if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new') if (typeof callback !== 'function') throw new TypeError('Argument must be a function') callback( function(val) { _resolve(_this, val) }, function(val) { _reject(_this, val) } ) } var self = { _state: 1, _fired: 1, _val: 1, callback: 1 } _Promise.prototype = { constructor: _Promise, _state: 'pending', _fired: false, _fire: function(yes, no) { if (this._state === 'rejected') { if (typeof no === 'function') no(this._val) else throw this._val } else { if (typeof yes === 'function') yes(this._val) } }, _then: function(yes, no) { if (this._fired) { var _this = this fireCallback(_this, function() { _this._fire(yes, no) }) } else { this.callback.push({ yes: yes, no: no }) } }, then: function(yes, no) { yes = typeof yes === 'function' ? yes : _yes no = typeof no === 'function' ? no : _no var _this = this var next = new _Promise(function(resolve, reject) { _this._then( function(val) { try { val = yes(val) } catch (err) { return reject(err) } }, function(val) { try { val = no(val) } catch (err) { return reject(err) } resolve(val) } ) }) for (var i in _this) { if (!self[i]) next[i] = _this[i] } return next }, done: done, catch: fail, fail: fail } _Promise.all = function(arr) { return _some(false, arr) } _Promise.race = function(arr) { return _some(true, arr) } _Promise.defer = defer _Promise.resolve = function(val) { var obj = this.defer() obj.resolve(val) return obj.promise } _Promise.reject = function(val) { var obj = this.defer() obj.reject(val) return obj.promise } // ----------------------------------------------------------- function _yes(val) { return val } function _no(err) { throw err } function done(callback) { return this.then(callback, _no) } function fail(callback) { return this.then(_yes, callback) } function defer() { var obj = {} obj.promise = new this(function(yes, no) { obj.resolve = yes obj.reject = no }) return obj } //成功的回调 function _resolve(obj, val) { if (obj._state !== 'pending') return if (val && typeof val.then === 'function') { var method = val instanceof _Promise ? '_then' : 'then' val[method]( function(v) { _transmit(obj, v, true) }, function(v) { _transmit(obj, v, false) } ) } else { _transmit(obj, val, true) } } //失败的回调 function _reject(obj, val) { if (obj._state !== 'pending') return _transmit(obj, val, false) } // 改变Promise的_fired值,并保持用户传参,触发所有回调 function _transmit(obj, val, isResolved) { obj._fired = true obj._val = val obj._state = isResolved ? 'fulfilled' : 'rejected' fireCallback(obj, function() { for (var i in obj.callback) { obj._fire(obj.callback[i].yes, obj.callback[i].no) } }) } function fireCallback(obj, callback) { var isAsync = false if (typeof obj.async === 'boolean') isAsync = obj.async else isAsync = obj.async = true if (isAsync) setTimeout(callback, 0) else callback() } function _some(bool, iterable) { iterable = Array.isArray(iterable) ? iterable : [] var n = 0 var res = [] var end = false return new _Promise(function(yes, no) { if (!iterable.length) no(res) function loop(obj, idx) { obj.then( function(val) { if (!end) { res[idx] = val n++ if (bool || n >= iterable.length) { yes(bool ? val : res) end = true } } }, function(val) { end = true no(val) } ) } for (var i = 0, len = iterable.length; i < len; i++) { loop(iterable[i], i) } }) } // --------------------------------------------------------------- var nativePromise = window.Promise if (/native code/.test(nativePromise)) { nativePromise.prototype.done = done nativePromise.prototype.fail = fail if (!nativePromise.defer) nativePromise.defer = defer } export default (window.Promise = nativePromise || _Promise)