This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0
wcui/js/lib/request/promise.js

224 lines
5.8 KiB
JavaScript
Raw Normal View History

2017-03-30 01:40:59 +08:00
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2016-11-26 16:35:45
*
*/
'use strict';
2017-03-30 01:40:59 +08:00
define(function() {
var _Promise = function(callback) {
this.callback = [];
var _this = this;
2017-03-30 01:40:59 +08:00
if (typeof this !== 'object')
throw new TypeError('Promises must be constructed via new');
2017-03-30 01:40:59 +08:00
if (typeof callback !== 'function')
throw new TypeError('Argument must be a function');
2017-03-30 01:40:59 +08:00
callback(
function(val) {
_resolve(_this, val);
},
function(val) {
_reject(_this, val);
}
);
};
2017-03-30 01:40:59 +08:00
var self = {
_state: 1,
_fired: 1,
_val: 1,
callback: 1
};
2017-03-30 01:40:59 +08:00
_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);
2017-03-30 01:40:59 +08:00
}
},
_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 });
2017-03-30 01:40:59 +08:00
}
},
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);
2017-03-30 01:40:59 +08:00
}
},
function(val) {
try {
val = no(val);
} catch (err) {
return reject(err);
2017-03-30 01:40:59 +08:00
}
resolve(val);
}
);
});
for (var i in _this) {
if (!self[i]) next[i] = _this[i];
2017-03-30 01:40:59 +08:00
}
return next;
2017-03-30 01:40:59 +08:00
},
done: done,
catch: fail,
fail: fail
};
2017-03-30 01:40:59 +08:00
_Promise.all = function(arr) {
return _some(false, arr);
};
2017-03-30 01:40:59 +08:00
_Promise.race = function(arr) {
return _some(true, arr);
};
2017-03-30 01:40:59 +08:00
_Promise.defer = defer;
2017-03-30 01:40:59 +08:00
// -----------------------------------------------------------
2017-03-30 01:40:59 +08:00
function _yes(val) {
return val;
2017-03-30 01:40:59 +08:00
}
function _no(err) {
throw err;
2017-03-30 01:40:59 +08:00
}
function done(callback) {
return this.then(callback, _no);
2017-03-30 01:40:59 +08:00
}
function fail(callback) {
return this.then(_yes, callback);
2017-03-30 01:40:59 +08:00
}
function defer() {
var obj = {};
obj.promise = new this(function(yes, no) {
obj.resolve = yes;
obj.reject = no;
});
return obj;
2017-03-30 01:40:59 +08:00
}
//成功的回调
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);
2017-03-30 01:40:59 +08:00
}
}
//失败的回调
function _reject(obj, val) {
if (obj._state !== 'pending') return;
2017-03-30 01:40:59 +08:00
_transmit(obj, val, false);
2017-03-30 01:40:59 +08:00
}
// 改变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);
2017-03-30 01:40:59 +08:00
}
});
2017-03-30 01:40:59 +08:00
}
function fireCallback(obj, callback) {
var isAsync = false;
2017-03-30 01:40:59 +08:00
if (typeof obj.async === 'boolean') isAsync = obj.async;
else isAsync = obj.async = true;
2017-03-30 01:40:59 +08:00
if (isAsync) setTimeout(callback, 0);
else callback();
2017-03-30 01:40:59 +08:00
}
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;
}
2017-03-30 01:40:59 +08:00
}
},
function(val) {
end = true;
no(val);
2017-03-30 01:40:59 +08:00
}
);
2017-03-30 01:40:59 +08:00
}
for (var i = 0, len = iterable.length; i < len; i++) {
loop(iterable[i], i);
2017-03-30 01:40:59 +08:00
}
});
2017-03-30 01:40:59 +08:00
}
// ---------------------------------------------------------------
2017-03-30 01:40:59 +08:00
var nativePromise = window.Promise;
if (/native code/.test(nativePromise)) {
nativePromise.prototype.done = done;
nativePromise.prototype.fail = fail;
if (!nativePromise.defer) nativePromise.defer = defer;
2017-03-30 01:40:59 +08:00
}
return (window.Promise = nativePromise || _Promise);
});