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

更新request模块, 支持end不传参(返回Promise对象)

old
宇天 2017-11-08 13:44:26 +08:00
parent 99c95cf4a6
commit b13b8573b9
2 changed files with 606 additions and 645 deletions

View File

@ -5,12 +5,13 @@
*
*/
"use strict";
define(['yua'], function(yua){
'use strict';
define(['yua', './promise'], function(yua) {
var _request = function(url, protocol) {
this.transport = true
protocol = (protocol + '').trim().toUpperCase()
this.xhr = Xhr()
this.transport = true;
protocol = (protocol + '').trim().toUpperCase();
this.xhr = Xhr();
this.defer = Promise.defer();
this.opt = {
url: (url + '').trim(),
type: protocol || 'GET',
@ -18,8 +19,10 @@ define(['yua'], function(yua){
data: {},
headers: {},
timeoutID: 0,
uuid: Math.random().toString(16).substr(2)
}
uuid: Math.random()
.toString(16)
.substr(2)
};
},
_requestp = _request.prototype,
toS = Object.prototype.toString,
@ -28,72 +31,64 @@ define(['yua'], function(yua){
encode = encodeURIComponent,
decode = decodeURIComponent,
noop = function(e, res) {
if(e)
throw new Error(e + '')
this.defer.resolve(res);
};
// -----------------------------
// 本地协议判断正则
var rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/
var isLocal = false
var rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/;
var isLocal = false;
try {
isLocal = rlocalProtocol.test(location.ptyperotocol)
isLocal = rlocalProtocol.test(location.ptyperotocol);
} catch (e) {}
var rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg
var rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/gm;
// ----------------- 一些兼容性预处理 --------------------
win.Xhr = function() {
return new XMLHttpRequest()
}
var supportCors = 'withCredentials' in Xhr()
return new XMLHttpRequest();
};
var supportCors = 'withCredentials' in Xhr();
// ------------------- 几个解释方法 -----------------------
function serialize(p, obj, q) {
var k
var k;
if (Array.isArray(obj)) {
obj.forEach(function(it, i) {
k = p ? (p + '[' + (Array.isArray(it) ? i : '') + ']') : i
k = p ? p + '[' + (Array.isArray(it) ? i : '') + ']' : i;
if (typeof it === 'object') {
serialize(k, it, q)
serialize(k, it, q);
} else {
q(k, it)
q(k, it);
}
})
});
} else {
for (var i in obj) {
k = p ? (p + '[' + i + ']') : i
k = p ? p + '[' + i + ']' : i;
if (typeof obj[i] === 'object') {
serialize(k, obj[i], q)
serialize(k, obj[i], q);
} else {
q(k, obj[i])
q(k, obj[i]);
}
}
}
}
}
var Format = function(){}
var Format = function() {};
Format.prototype = {
parseJS: function(code) {
code = (code + '').trim()
code = (code + '').trim();
if (code) {
if (code.indexOf('use strict') === 1) {
var script = doc.createElement('script')
script.text = code
doc.head
.appendChild(script)
.parentNode
.removeChild(script)
var script = doc.createElement('script');
script.text = code;
doc.head.appendChild(script).parentNode.removeChild(script);
} else {
eval(code)
eval(code);
}
}
},
@ -105,54 +100,53 @@ define(['yua'], function(yua){
xml = void 0;
}
if(!xml ||
if (
!xml ||
!xml.documentElement ||
xml.getElementsByTagName('parsererror').length){
console.error('Invalid XML: ' + data)
xml.getElementsByTagName('parsererror').length
) {
console.error('Invalid XML: ' + data);
}
return xml
return xml;
},
parseHTML: function(html) {
return yua.parseHTML(html)
return yua.parseHTML(html);
},
param: function(obj) {
if (!obj || typeof obj === 'string' || typeof obj === 'number')
return obj
return obj;
var arr = []
var arr = [];
var q = function(k, v) {
if(/native code/.test(v))
return
if (/native code/.test(v)) return;
v = (typeof v === 'function') ? v() : v
v = (toS.call(v) !== '[object File]') ? encode(v) : v
v = typeof v === 'function' ? v() : v;
v = toS.call(v) !== '[object File]' ? encode(v) : v;
arr.push(encode(k) + '=' + v)
}
arr.push(encode(k) + '=' + v);
};
if(typeof obj === 'object')
serialize('', obj, q)
if (typeof obj === 'object') serialize('', obj, q);
return arr.join('&')
return arr.join('&');
},
parseForm: function(form) {
var data = {}
for(var i = 0,field; field = form.elements[i++];){
var data = {};
for (var i = 0, field; (field = form.elements[i++]); ) {
switch (field.type) {
case 'select-one':
case 'select-multiple':
if (field.name.length && !field.disabled) {
for(var j = 0, opt;opt = field.options[j++];){
for (var j = 0, opt; (opt = field.options[j++]); ) {
if (opt.selected) {
data[field.name] = opt.value || opt.text
data[field.name] = opt.value || opt.text;
}
}
}
break;
case 'file':
if (field.name.length && !field.disabled) {
data[field.name] = field.files[0]
data[field.name] = field.files[0];
}
break;
case undefined:
@ -163,96 +157,84 @@ define(['yua'], function(yua){
case 'radio':
case 'checkbox':
// 只处理选中的
if(!field.checked)
break;
if (!field.checked) break;
default:
if (field.name.length && !field.disabled) {
data[field.name] = field.value
data[field.name] = field.value;
}
}
}
return data
return data;
},
merge: function(a, b) {
if (typeof a !== 'object' || typeof b !== 'object')
throw new TypeError('argument must be an object')
throw new TypeError('argument must be an object');
if(Object.assign)
return Object.assign(a, b)
if (Object.assign) return Object.assign(a, b);
for (var i in b) {
a[i] = b[i]
}
return a
a[i] = b[i];
}
return a;
}
};
var F = new Format()
var F = new Format();
// ---------------------------------------------------------
// -------------------- request 模块开始 --------------------
// ---------------------------------------------------------
var requestConvert = {
text: function(val) {
return val
return val;
},
xml: function(val, xml) {
return xml !== undefined ? xml : F.parseXML(val)
return xml !== undefined ? xml : F.parseXML(val);
},
html: function(val) {
return F.parseHTML(val)
return F.parseHTML(val);
},
json: function(val) {
return JSON.parse(val)
return JSON.parse(val);
},
script: function(val) {
return F.parseJS(val)
return F.parseJS(val);
},
jsonp: function(name) {
var json = request.cache[name]
var json = request.cache[name];
delete request.cache[name];
return json
}
return json;
}
};
var requestExtend = {
formData: function() {
if (this.opt.form) {
var data = F.parseForm(this.opt.form)
F.merge(this.opt.data, data)
var data = F.parseForm(this.opt.form);
F.merge(this.opt.data, data);
}
var form = new FormData()
var form = new FormData();
for (var i in this.opt.data) {
var el = this.opt.data[i]
var el = this.opt.data[i];
if (Array.isArray(el)) {
el.forEach(function(it) {
form.append(i + '[]', it)
})
form.append(i + '[]', it);
});
} else {
form.append(i, this.opt.data[i])
form.append(i, this.opt.data[i]);
}
}
return form
return form;
},
jsonp: function(jsonpcallback) {
win[jsonpcallback] = function(val) {
delete win[jsonpcallback]
request.cache[jsonpcallback] = val
}
delete win[jsonpcallback];
request.cache[jsonpcallback] = val;
};
},
dispatch: function(self) {
if(!this.transport)
return
if (!this.transport) return this.defer.reject('Request pending...');
var _this = this,
result = {
@ -274,260 +256,272 @@ define(['yua'], function(yua){
//状态为4,既已成功, 则清除超时
clearTimeout(_this.opt.timeoutID);
if(typeof this.transport === 'object'
&& this.opt.type === 'JSONP'){
if (
typeof this.transport === 'object' &&
this.opt.type === 'JSONP'
) {
//移除script
// this.transport.parentNode.removeChild(this.transport);
//超时返回
if (self !== null) {
var exec = !this.transport.readyState
|| this.transport.readyState === 'loaded'
|| this.transport.readyState === 'complete';
var exec =
!this.transport.readyState ||
this.transport.readyState === 'loaded' ||
this.transport.readyState === 'complete';
if (exec) {
result.body = requestConvert.jsonp(this.opt.data.callback)
result.text = JSON.stringify(result.body)
result.body = requestConvert.jsonp(
this.opt.data.callback
);
result.text = JSON.stringify(result.body);
}
}
this.callback(result.error, result)
this.callback(result.error, result);
} else {
//成功的回调
var isSucc = self ? ((self.status >= 200 && self.status < 300) || self.status === 304) : false,
headers = self && self.getAllResponseHeaders().split('\n') || [];
var isSucc = self
? (self.status >= 200 && self.status < 300) ||
self.status === 304
: false,
headers =
(self && self.getAllResponseHeaders().split('\n')) ||
[];
//处理返回的Header
headers.forEach(function(it, i) {
it = it.trim()
it = it.trim();
if (it) {
it = it.split(':')
result.response.headers[it.shift().toLowerCase()] = it.join(':').trim()
it = it.split(':');
result.response.headers[
it.shift().toLowerCase()
] = it.join(':').trim();
}
});
if (isSucc) {
result.status = self.status
result.status = self.status;
if (result.status === 204) {
result.statusText = 'no content'
result.statusText = 'no content';
} else if (result.status === 304) {
result.statusText = 'not modified'
result.statusText = 'not modified';
}
} else {
result.status = self === null ? 504 : (self.status || 500)
result.statusText = self === null ? 'Connected timeout' : (self.statusText || 'Internal Server Error')
result.error = F.merge(new Error(result.statusText), {status: result.status})
result.status = self === null ? 504 : self.status || 500;
result.statusText =
self === null
? 'Connected timeout'
: self.statusText || 'Internal Server Error';
result.error = F.merge(new Error(result.statusText), {
status: result.status
});
}
try {
//处理返回的数据
var dataType = result.response.headers['content-type'].match(/json|xml|script|html/i) || ['text']
var dataType = result.response.headers[
'content-type'
].match(/json|xml|script|html/i) || ['text'];
dataType = dataType[0].toLowerCase()
result.text = self && (self.responseText || self.responseXML) || ''
result.body = requestConvert[dataType](result.text, self && self.responseXML)
dataType = dataType[0].toLowerCase();
result.text =
(self && (self.responseText || self.responseXML)) || '';
result.body = requestConvert[dataType](
result.text,
self && self.responseXML
);
} catch (err) {
result.error = err
result.statusText = 'parse error'
result.error = err;
result.statusText = 'parse error';
}
_this.callback(result.error, result)
_this.callback(result.error, result);
}
delete _this.defer;
delete _this.transport;
delete _this.opt
delete _this.xhr
}
delete _this.opt;
delete _this.xhr;
}
};
// 设置表单类型, 支持2种, form/json
_requestp.type = function(t) {
if(this.opt.formType === 'form-data')
return this
if (this.opt.formType === 'form-data') return this;
this.opt.formType = t || 'form'
this.opt.formType = t || 'form';
if (t === 'form' || this.opt.type === 'GET')
this.set('content-type', 'application/x-www-form-urlencoded; charset=UTF-8')
else
this.set('content-type', 'application/json; charset=UTF-8')
this.set(
'content-type',
'application/x-www-form-urlencoded; charset=UTF-8'
);
else this.set('content-type', 'application/json; charset=UTF-8');
return this
}
return this;
};
//设置头信息
_requestp.set = function(k, val) {
if(!this.transport)
return
if (!this.transport) return;
if (typeof k === 'object') {
for (var i in k) {
i = i.toLowerCase()
this.opt.headers[i] = k[i]
i = i.toLowerCase();
this.opt.headers[i] = k[i];
}
} else if (typeof k === 'string') {
if(arguments.length < 2)
throw new Error('2 arguments required')
if (arguments.length < 2) throw new Error('2 arguments required');
// 全转小写,避免重复写入
k = k.toLowerCase()
k = k.toLowerCase();
if(val === undefined)
delete this.opt.headers[k]
else
this.opt.headers[k] = val
if (val === undefined) delete this.opt.headers[k];
else this.opt.headers[k] = val;
} else {
throw new Error('arguments must be string/object, but [' + (typeof k) + '] given')
}
return this
throw new Error(
'arguments must be string/object, but [' + typeof k + '] given'
);
}
return this;
};
//设置请求参数
_requestp.send = function(k, val) {
if(!this.transport)
return
if (!this.transport) return;
// 1. send方法可以多次调用, 但必须保证格式一致
// 2. 2次圴提交纯字符串也会抛出异常
if (typeof k === 'object') {
if(this.opt.data && (typeof this.opt.data === 'string'))
throw new Error('param can not be string and object at the same time')
if(!this.opt.data)
this.opt.data = {}
if (this.opt.data && typeof this.opt.data === 'string')
throw new Error(
'param can not be string and object at the same time'
);
if (!this.opt.data) this.opt.data = {};
F.merge(this.opt.data, k)
F.merge(this.opt.data, k);
} else {
if (typeof k === 'string') {
if (arguments.length === 1) {
if (this.opt.data)
throw new Error('invalid param in function send')
throw new Error('invalid param in function send');
this.opt.data = k
this.opt.data = k;
} else {
if(this.opt.data && (typeof this.opt.data === 'string'))
throw new Error('param can not be string and object at the same time')
if (this.opt.data && typeof this.opt.data === 'string')
throw new Error(
'param can not be string and object at the same time'
);
if(!this.opt.data)
this.opt.data = {}
if (!this.opt.data) this.opt.data = {};
this.opt.data[k] = val
this.opt.data[k] = val;
}
} else {
throw new Error('argument of send must be string/object, but [' + (typeof k) + '] given')
throw new Error(
'argument of send must be string/object, but [' +
typeof k +
'] given'
);
}
}
}
return this
}
return this;
};
//该方法用于 form-data类型的post请求的参数设置
_requestp.field = function(k, val) {
if(!this.transport)
return this
if (!this.transport) return this;
// 此类型优先级最高
this.opt.formType = 'form-data'
this.opt.type = 'POST'
if(!this.opt.data || (this.opt.data && typeof this.opt.data !== 'object'))
this.opt.data = {}
this.opt.formType = 'form-data';
this.opt.type = 'POST';
if (
!this.opt.data ||
(this.opt.data && typeof this.opt.data !== 'object')
)
this.opt.data = {};
if (arguments.length === 1 && typeof k === 'object') {
F.merge(this.opt.data, k)
F.merge(this.opt.data, k);
} else if (arguments.length === 2) {
this.opt.data[k] = val
this.opt.data[k] = val;
} else {
throw new TypeError('argument must be an object, but ' + (typeof k) + ' given')
throw new TypeError(
'argument must be an object, but ' + typeof k + ' given'
);
}
return this
}
return this;
};
//设置缓存
_requestp.cache = function(t) {
if(!this.transport)
return
if (!this.transport) return;
if(this.opt.type === 'GET')
this.opt.cache = !!t
return this
}
if (this.opt.type === 'GET') this.opt.cache = !!t;
return this;
};
//取消网络请求
_requestp.abort = function() {
delete this.transport
if(!this.opt.form)
this.xhr.abort()
delete this.transport;
if (!this.opt.form) this.xhr.abort();
return this
}
return this;
};
//超时设置, 单位毫秒
_requestp.timeout = function(time) {
if(typeof time !== 'number' || time < 1)
return this
this.opt.timeout = time
return this
}
if (typeof time !== 'number' || time < 1) return this;
this.opt.timeout = time;
return this;
};
_requestp.form = function(form) {
if (typeof form === 'object' && form.nodeName === 'FORM') {
this.opt.type = 'POST'
this.opt.form = form
}
return this
this.opt.type = 'POST';
this.opt.form = form;
}
return this;
};
var originAnchor = doc.createElement('a');
originAnchor.href = location.href;
_requestp.end = function(callback) {
var _this = this;
// 回调已执行, 或已取消, 则直接返回, 防止重复执行
if(!this.transport)
return this
if (!this.transport) return this;
if(!this.opt.url)
throw new Error('Invalid request url')
if (!this.opt.url) throw new Error('Invalid request url');
F.merge(this, requestExtend)
F.merge(this, requestExtend);
this.callback = callback || noop
this.callback = callback || noop.bind(this);
// 1. url规范化
this.opt.url = this.opt.url.replace(/#.*$/, '').replace(/^\/\//, location.protocol + '//')
this.opt.url = this.opt.url
.replace(/#.*$/, '')
.replace(/^\/\//, location.protocol + '//');
// 2. 处理跨域
if (typeof this.opt.crossDomain !== 'boolean') {
var anchor = doc.createElement('a')
var anchor = doc.createElement('a');
try {
anchor.href = this.opt.url
anchor.href = this.opt.url;
// IE7及以下浏览器 '1'[0]的结果是 undefined
// IE7下需要获取绝对路径
var absUrl = !'1'[0] ? anchor.getAttribute('href', 4) : anchor.href
anchor.href = absUrl
anchor.async = true
this.opt.crossDomain = (originAnchor.protocol !== anchor.protocol) || (originAnchor.host !== anchor.host)
var absUrl = !'1'[0]
? anchor.getAttribute('href', 4)
: anchor.href;
anchor.href = absUrl;
anchor.async = true;
this.opt.crossDomain =
originAnchor.protocol !== anchor.protocol ||
originAnchor.host !== anchor.host;
} catch (e) {
this.opt.crossDomain = true
this.opt.crossDomain = true;
}
}
@ -537,145 +531,126 @@ define(['yua'], function(yua){
if (!this.opt.crossDomain) {
this.opt.type = 'GET';
} else {
this.opt.data['callback'] = this.opt.data['callback'] || ('jsonp' + request.cid++);
this.opt.data['callback'] =
this.opt.data['callback'] || 'jsonp' + request.cid++;
this.jsonp(this.opt.data['callback']); //创建临时处理方法
}
}
// 2.2 如果不是跨域请求则自动加上一条header信息用以标识这是ajax请求
if (!this.opt.crossDomain) {
this.set('X-Requested-With', 'XMLHttpRequest')
this.set('X-Requested-With', 'XMLHttpRequest');
} else {
supportCors && (this.xhr.withCredentials = true)
supportCors && (this.xhr.withCredentials = true);
}
// 3. data转字符串
this.opt.param = F.param(this.opt.data)
this.opt.param = F.param(this.opt.data);
// 4. 设置Content-Type类型, 默认x-www-form-urlencoded
if(!this.opt.formType)
this.type('form')
if (!this.opt.formType) this.type('form');
// 5.处理GET请求
this.opt.hasContent = this.opt.type === 'POST' //是否为post请求
this.opt.hasContent = this.opt.type === 'POST'; //是否为post请求
if (!this.opt.hasContent) {
//GET请求直接把参数拼接到url上
if (this.opt.param) {
this.opt.url += (/\?/.test(this.opt.url) ? '&' : '?') + this.opt.param
this.opt.url +=
(/\?/.test(this.opt.url) ? '&' : '?') + this.opt.param;
}
//加随机值,避免缓存
if (this.opt.cache === false)
this.opt.url += (/\?/.test(this.opt.url) ? '&' : '?') + '_=' + Math.random()
this.opt.url +=
(/\?/.test(this.opt.url) ? '&' : '?') +
'_=' +
Math.random();
} else {
if (this.opt.formType === 'form-data') {
delete this.opt.headers['content-type']
this.opt.param = this.formData()
delete this.opt.headers['content-type'];
this.opt.param = this.formData();
} else if (this.opt.formType !== 'form') {
this.opt.param = JSON.stringify(this.opt.data)
this.opt.param = JSON.stringify(this.opt.data);
}
}
//jsonp
if (this.opt.type === 'JSONP') {
this.transport = doc.createElement('script')
this.transport = doc.createElement('script');
this.transport.onerror = this.transport.onload = function() {
_this.dispatch(_this.transport)
}
this.transport.src = this.opt.url
doc.head.insertBefore(this.transport, doc.head.firstChild)
_this.dispatch(_this.transport);
};
this.transport.src = this.opt.url;
doc.head.insertBefore(this.transport, doc.head.firstChild);
//6. 超时处理
if (this.opt.timeout && this.opt.timeout > 0) {
this.opt.timeoutID = setTimeout(function() {
_this.transport.onerror = _this.transport.onload = null
_this.dispatch(null)
}, this.opt.timeout)
_this.transport.onerror = _this.transport.onload = null;
_this.dispatch(null);
}, this.opt.timeout);
}
} else {
this.xhr.onreadystatechange = function(ev) {
if (_this.opt.timeout && _this.opt.timeout > 0) {
_this.opt['time' + this.readyState] = ev.timeStamp
_this.opt['time' + this.readyState] = ev.timeStamp;
if (this.readyState === 4) {
_this.opt.isTimeout = _this.opt.time4 - _this.opt.time1 > _this.opt.timeout
_this.opt.isTimeout =
_this.opt.time4 - _this.opt.time1 >
_this.opt.timeout;
}
}
if (this.readyState !== 4) {
return
}
_this.dispatch(_this.opt.isTimeout ? null : _this.xhr)
return;
}
_this.dispatch(_this.opt.isTimeout ? null : _this.xhr);
};
// 6. 初始化xhr提交
this.xhr.open(this.opt.type, this.opt.url, true)
this.xhr.open(this.opt.type, this.opt.url, true);
// 7. 设置头信息
for (var i in this.opt.headers) {
if (this.opt.headers[i])
this.xhr.setRequestHeader(i, this.opt.headers[i])
this.xhr.setRequestHeader(i, this.opt.headers[i]);
}
// 8. 发起网络请求
_this.xhr.send(_this.opt.param)
_this.xhr.send(_this.opt.param);
//超时处理
if (this.opt.timeout && this.opt.timeout > 0) {
this.xhr.timeout = this.opt.timeout;
}
}
return this
}
return this.defer.promise;
};
// ---------------------- end ------------------------
if (!win.request) {
win.request = {
get: function(url) {
if(!url)
throw new Error('argument url is required')
if (!url) throw new Error('argument url is required');
return new _request(url, 'GET')
return new _request(url, 'GET');
},
post: function(url) {
if(!url)
throw new Error('argument url is required')
if (!url) throw new Error('argument url is required');
return new _request(url, 'POST')
return new _request(url, 'POST');
},
jsonp: function(url) {
if(!url)
throw new Error('argument url is required')
if (!url) throw new Error('argument url is required');
return new _request(url, 'JSONP')
return new _request(url, 'JSONP');
},
cache: {},
cid: 0,
version: '1.0.0-es5',
}
yua.ui.request = request.version
version: '1.1.0-es5'
};
yua.ui.request = request.version;
}
return request
})
return request;
});

View File

@ -5,32 +5,34 @@
*
*/
"use strict";
'use strict';
define(function() {
var _Promise = function(callback) {
this.callback = []
var _this = this
this.callback = [];
var _this = this;
if (typeof this !== 'object')
throw new TypeError('Promises must be constructed via new')
throw new TypeError('Promises must be constructed via new');
if (typeof callback !== 'function')
throw new TypeError('Argument must be a function')
throw new TypeError('Argument must be a function');
callback(function(val){
_resolve(_this, val)
}, function(val){
_reject(_this, val)
})
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,
@ -38,200 +40,184 @@ define(function(){
_fired: false,
_fire: function(yes, no) {
if (this._state === 'rejected') {
if(typeof no === 'function')
no(this._val)
else
throw this._val
if (typeof no === 'function') no(this._val);
else throw this._val;
} else {
if(typeof yes === 'function')
yes(this._val)
if (typeof yes === 'function') yes(this._val);
}
},
_then: function(yes, no) {
if (this._fired) {
var _this = this
var _this = this;
fireCallback(_this, function() {
_this._fire(yes, no)
})
_this._fire(yes, no);
});
} else {
this.callback.push({yes: yes, no: no})
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
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){
_this._then(
function(val) {
try {
val = yes(val)
val = yes(val);
} catch (err) {
return reject(err)
return reject(err);
}
}, function(val){
},
function(val) {
try {
val = no(val)
val = no(val);
} catch (err) {
return reject(err)
return reject(err);
}
resolve(val)
})
})
resolve(val);
}
);
});
for (var i in _this) {
if(!self[i])
next[i] = _this[i]
if (!self[i]) next[i] = _this[i];
}
return next
return next;
},
done: done,
catch: fail,
fail: fail
}
};
_Promise.all = function(arr) {
return _some(false, arr)
}
return _some(false, arr);
};
_Promise.race = function(arr) {
return _some(true, arr)
}
return _some(true, arr);
};
_Promise.defer = defer
_Promise.defer = defer;
// -----------------------------------------------------------
function _yes(val) {
return val
return val;
}
function _no(err) {
throw err
throw err;
}
function done(callback) {
return this.then(callback, _no)
return this.then(callback, _no);
}
function fail(callback) {
return this.then(_yes, callback)
return this.then(_yes, callback);
}
function defer() {
var obj = {}
var obj = {};
obj.promise = new this(function(yes, no) {
obj.resolve = yes
obj.reject = no
})
return obj
obj.resolve = yes;
obj.reject = no;
});
return obj;
}
//成功的回调
function _resolve(obj, val) {
if(obj._state !== 'pending')
return
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)
})
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)
_transmit(obj, val, true);
}
}
//失败的回调
function _reject(obj, val) {
if(obj._state !== 'pending')
return
if (obj._state !== 'pending') return;
_transmit(obj, val, false)
_transmit(obj, val, false);
}
// 改变Promise的_fired值并保持用户传参触发所有回调
function _transmit(obj, val, isResolved) {
obj._fired = true
obj._val = val
obj._state = isResolved ? 'fulfilled' : 'rejected'
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)
obj._fire(obj.callback[i].yes, obj.callback[i].no);
}
})
});
}
function fireCallback(obj, callback) {
var isAsync = false
var isAsync = false;
if(typeof obj.async === 'boolean')
isAsync = obj.async
else
isAsync = obj.async = true
if (typeof obj.async === 'boolean') isAsync = obj.async;
else isAsync = obj.async = true;
if(isAsync)
setTimeout(callback, 0)
else
callback()
if (isAsync) setTimeout(callback, 0);
else callback();
}
function _some(bool, iterable) {
iterable = Array.isArray(iterable) ? iterable : []
iterable = Array.isArray(iterable) ? iterable : [];
var n = 0
var res = []
var end = false
var n = 0;
var res = [];
var end = false;
return new _Promise(function(yes, no) {
if(!iterable.length)
no(res)
if (!iterable.length) no(res);
function loop(obj, idx) {
obj.then(function(val){
obj.then(
function(val) {
if (!end) {
res[idx] = val
n++
res[idx] = val;
n++;
if (bool || n >= iterable.length) {
yes(bool ? val : res)
end = true
yes(bool ? val : res);
end = true;
}
}
}, function(val){
end = true
no(val)
})
},
function(val) {
end = true;
no(val);
}
);
}
for (var i = 0, len = iterable.length; i < len; i++) {
loop(iterable[i], i)
loop(iterable[i], i);
}
})
});
}
// ---------------------------------------------------------------
var nativePromise = window.Promise
var nativePromise = window.Promise;
if (/native code/.test(nativePromise)) {
nativePromise.prototype.done = done
nativePromise.prototype.fail = fail
if(!nativePromise.defer)
nativePromise.defer = defer
nativePromise.prototype.done = done;
nativePromise.prototype.fail = fail;
if (!nativePromise.defer) nativePromise.defer = defer;
}
return window.Promise = nativePromise || _Promise
})
return (window.Promise = nativePromise || _Promise);
});