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

238 lines
5.6 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";
define(function(){
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
// -----------------------------------------------------------
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
}
return window.Promise = nativePromise || _Promise
})