diff --git a/js/lib/request/es5.js b/js/lib/request/es5.js index c014b4d..b6600e2 100644 --- a/js/lib/request/es5.js +++ b/js/lib/request/es5.js @@ -5,12 +5,13 @@ * */ -"use strict"; -define(['yua'], function(yua){ - var _request = function(url, protocol){ - this.transport = true - protocol = (protocol + '').trim().toUpperCase() - this.xhr = Xhr() +'use strict'; +define(['yua', './promise'], function(yua) { + var _request = function(url, protocol) { + this.transport = true; + protocol = (protocol + '').trim().toUpperCase(); + this.xhr = Xhr(); + this.defer = Promise.defer(); this.opt = { url: (url + '').trim(), type: protocol || 'GET', @@ -18,141 +19,134 @@ 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, - win = window, - doc = win.document, - encode = encodeURIComponent, - decode = decodeURIComponent, - noop = function(e, res){ - if(e) - throw new Error(e + '') - }; + _requestp = _request.prototype, + toS = Object.prototype.toString, + win = window, + doc = win.document, + encode = encodeURIComponent, + decode = decodeURIComponent, + noop = function(e, res) { + this.defer.resolve(res); + }; // ----------------------------- - + // 本地协议判断正则 - var rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/ - var isLocal = false - try{ - isLocal = rlocalProtocol.test(location.ptyperotocol) - }catch(e){} + var rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/; + var isLocal = false; + try { + 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() + win.Xhr = function() { + return new XMLHttpRequest(); + }; + var supportCors = 'withCredentials' in Xhr(); // ------------------- 几个解释方法 ----------------------- - - - function serialize(p, obj, q){ - var k - if(Array.isArray(obj)){ - obj.forEach(function(it, i){ - k = p ? (p + '[' + (Array.isArray(it) ? i : '') + ']') : i - if(typeof it === 'object'){ - serialize(k, it, q) - }else{ - q(k, it) + function serialize(p, obj, q) { + var k; + if (Array.isArray(obj)) { + obj.forEach(function(it, i) { + k = p ? p + '[' + (Array.isArray(it) ? i : '') + ']' : i; + if (typeof it === 'object') { + serialize(k, it, q); + } else { + q(k, it); } - }) - }else{ - for(var i in obj){ - k = p ? (p + '[' + i + ']') : i - if(typeof obj[i] === 'object'){ - serialize(k, obj[i], q) - }else{ - q(k, obj[i]) + }); + } else { + for (var i in obj) { + k = p ? p + '[' + i + ']' : i; + if (typeof obj[i] === 'object') { + serialize(k, obj[i], q); + } else { + q(k, obj[i]); } } } - } - var Format = function(){} + var Format = function() {}; Format.prototype = { - parseJS: function(code){ - 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) - }else{ - eval(code) + parseJS: function(code) { + 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); + } else { + eval(code); } } }, - parseXML: function(data, xml, tmp){ - try{ + parseXML: function(data, xml, tmp) { + try { tmp = new DOMParser(); xml = tmp.parseFromString(data, 'text/xml'); - }catch(e){ + } catch (e) { 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) + parseHTML: function(html) { + return yua.parseHTML(html); }, - param: function(obj){ - if(!obj || typeof obj === 'string' || typeof obj === 'number') - return obj + param: function(obj) { + if (!obj || typeof obj === 'string' || typeof obj === 'number') + return obj; - var arr = [] - var q = function(k, v){ - if(/native code/.test(v)) - return + var arr = []; + var q = function(k, v) { + 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) - } - - if(typeof obj === 'object') - serialize('', obj, q) - - return arr.join('&') + arr.push(encode(k) + '=' + v); + }; + + if (typeof obj === 'object') serialize('', obj, q); + + return arr.join('&'); }, - parseForm: function(form){ - var data = {} - for(var i = 0,field; field = form.elements[i++];){ - - switch(field.type){ + parseForm: function(form) { + 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++];){ - if(opt.selected){ - data[field.name] = opt.value || opt.text + if (field.name.length && !field.disabled) { + for (var j = 0, opt; (opt = field.options[j++]); ) { + if (opt.selected) { + data[field.name] = opt.value || opt.text; } } } break; case 'file': - if(field.name.length && !field.disabled){ - data[field.name] = field.files[0] + if (field.name.length && !field.disabled) { + data[field.name] = field.files[0]; } break; case undefined: @@ -163,519 +157,500 @@ 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 + if (field.name.length && !field.disabled) { + 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') + merge: function(a, b) { + if (typeof a !== 'object' || typeof b !== '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] + for (var i in b) { + a[i] = b[i]; } - return a + return a; } - } - - - var F = new Format() + }; + var F = new Format(); // --------------------------------------------------------- // -------------------- request 模块开始 -------------------- // --------------------------------------------------------- - var requestConvert = { - text: function(val){ - return val - }, - xml: function(val, xml){ - return xml !== undefined ? xml : F.parseXML(val) - }, - html: function(val){ - return F.parseHTML(val) - }, - json: function(val){ - return JSON.parse(val) - }, - script: function(val){ - return F.parseJS(val) - }, - jsonp: function(name){ - var json = request.cache[name] - delete request.cache[name]; - return json - } + text: function(val) { + return val; + }, + xml: function(val, xml) { + return xml !== undefined ? xml : F.parseXML(val); + }, + html: function(val) { + return F.parseHTML(val); + }, + json: function(val) { + return JSON.parse(val); + }, + script: function(val) { + return F.parseJS(val); + }, + jsonp: function(name) { + var json = request.cache[name]; + delete request.cache[name]; + return json; } + }; var requestExtend = { - formData: function(){ - - if(this.opt.form){ - var data = F.parseForm(this.opt.form) - F.merge(this.opt.data, data) - } - - var form = new FormData() - for(var i in this.opt.data){ - var el = this.opt.data[i] - if(Array.isArray(el)){ - el.forEach(function(it){ - form.append(i + '[]', it) - }) - }else{ - form.append(i, this.opt.data[i]) - } - } - return form - - }, - jsonp: function(jsonpcallback){ - win[jsonpcallback] = function(val){ - delete win[jsonpcallback] - request.cache[jsonpcallback] = val - } - }, - dispatch: function(self){ - - - if(!this.transport) - return - - var _this = this, - result = { - response: { - url: this.opt.url, - headers: {'content-type': ''} - }, - request: { - url: this.opt.url, - headers: _this.opt.headers - }, - status: self === null ? 504 : 200, - statusText: self === null ? 'Connected timeout' : 'ok', - text: '', - body: '', - error: null - }; - - //状态为4,既已成功, 则清除超时 - clearTimeout(_this.opt.timeoutID); - - 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'; - - if(exec){ - result.body = requestConvert.jsonp(this.opt.data.callback) - result.text = JSON.stringify(result.body) - } - } - - 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') || []; - - //处理返回的Header - headers.forEach(function(it, i){ - it = it.trim() - if(it){ - it = it.split(':') - result.response.headers[it.shift().toLowerCase()] = it.join(':').trim() - } - - }); - - - if(isSucc){ - result.status = self.status - if(result.status === 204){ - result.statusText = 'no content' - }else if(result.status === 304){ - 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}) - } - - try{ - //处理返回的数据 - 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) - }catch(err){ - result.error = err - result.statusText = 'parse error' - } - - _this.callback(result.error, result) - - - - } - delete _this.transport; - delete _this.opt - delete _this.xhr - - + formData: function() { + if (this.opt.form) { + var data = F.parseForm(this.opt.form); + F.merge(this.opt.data, data); } + + var form = new FormData(); + for (var i in this.opt.data) { + var el = this.opt.data[i]; + if (Array.isArray(el)) { + el.forEach(function(it) { + form.append(i + '[]', it); + }); + } else { + form.append(i, this.opt.data[i]); + } + } + return form; + }, + jsonp: function(jsonpcallback) { + win[jsonpcallback] = function(val) { + delete win[jsonpcallback]; + request.cache[jsonpcallback] = val; + }; + }, + dispatch: function(self) { + if (!this.transport) return this.defer.reject('Request pending...'); + + var _this = this, + result = { + response: { + url: this.opt.url, + headers: { 'content-type': '' } + }, + request: { + url: this.opt.url, + headers: _this.opt.headers + }, + status: self === null ? 504 : 200, + statusText: self === null ? 'Connected timeout' : 'ok', + text: '', + body: '', + error: null + }; + + //状态为4,既已成功, 则清除超时 + clearTimeout(_this.opt.timeoutID); + + 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'; + + if (exec) { + result.body = requestConvert.jsonp( + this.opt.data.callback + ); + result.text = JSON.stringify(result.body); + } + } + + 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')) || + []; + + //处理返回的Header + headers.forEach(function(it, i) { + it = it.trim(); + if (it) { + it = it.split(':'); + result.response.headers[ + it.shift().toLowerCase() + ] = it.join(':').trim(); + } + }); + + if (isSucc) { + result.status = self.status; + if (result.status === 204) { + result.statusText = 'no content'; + } else if (result.status === 304) { + 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 + }); + } + + try { + //处理返回的数据 + 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 + ); + } catch (err) { + result.error = err; + result.statusText = 'parse error'; + } + + _this.callback(result.error, result); + } + delete _this.defer; + delete _this.transport; + delete _this.opt; + delete _this.xhr; } + }; // 设置表单类型, 支持2种, form/json - _requestp.type = function(t){ - if(this.opt.formType === 'form-data') - return this + _requestp.type = function(t) { + if (this.opt.formType === 'form-data') return this; - 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.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'); - return this - } + return this; + }; //设置头信息 - _requestp.set = function(k, val){ - if(!this.transport) - return + _requestp.set = function(k, val) { + if (!this.transport) return; - if(typeof k === 'object'){ - for(var i in k){ - i = i.toLowerCase() - this.opt.headers[i] = k[i] + if (typeof k === 'object') { + for (var i in k) { + i = i.toLowerCase(); + this.opt.headers[i] = k[i]; } - - }else if(typeof k === 'string'){ - if(arguments.length < 2) - throw new Error('2 arguments required') + } else if (typeof k === 'string') { + 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 - }else{ - throw new Error('arguments must be string/object, but [' + (typeof k) + '] given') + 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 - } + return this; + }; //设置请求参数 - _requestp.send = function(k, val){ - - if(!this.transport) - return + _requestp.send = function(k, val) { + 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 (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 = {}; - 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') + 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'); - 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') + 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) - 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') + } else { + 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 + _requestp.field = function(k, val) { + 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) - }else if(arguments.length === 2){ - this.opt.data[k] = val - }else{ - throw new TypeError('argument must be an object, but ' + (typeof k) + ' given') + if (arguments.length === 1 && typeof k === 'object') { + F.merge(this.opt.data, k); + } else if (arguments.length === 2) { + this.opt.data[k] = val; + } else { + throw new TypeError( + 'argument must be an object, but ' + typeof k + ' given' + ); } - return this - } - + return this; + }; //设置缓存 - _requestp.cache = function(t){ - if(!this.transport) - return + _requestp.cache = function(t) { + 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() + _requestp.abort = function() { + 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 + _requestp.timeout = function(time) { + if (typeof time !== 'number' || time < 1) return this; - this.opt.timeout = time - 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 + _requestp.form = function(form) { + if (typeof form === 'object' && form.nodeName === 'FORM') { + this.opt.type = 'POST'; + this.opt.form = form; } - - return this - } + return this; + }; var originAnchor = doc.createElement('a'); originAnchor.href = location.href; - _requestp.end = function(callback){ + _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') - try{ - anchor.href = this.opt.url + if (typeof this.opt.crossDomain !== 'boolean') { + var anchor = doc.createElement('a'); + try { + 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) - }catch(e){ - this.opt.crossDomain = true + 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; } } // 2.1 进一步处理跨域配置 - if(this.opt.type === 'JSONP'){ + if (this.opt.type === 'JSONP') { //如果没有跨域,自动转回xhr GET - if(!this.opt.crossDomain){ + if (!this.opt.crossDomain) { this.opt.type = 'GET'; - }else{ - this.opt.data['callback'] = this.opt.data['callback'] || ('jsonp' + request.cid++); + } else { + 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') - }else{ - supportCors && (this.xhr.withCredentials = true) + if (!this.opt.crossDomain) { + this.set('X-Requested-With', 'XMLHttpRequest'); + } else { + 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请求 - if(!this.opt.hasContent){ - + 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 + if (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() - }else{ - if(this.opt.formType === 'form-data'){ - 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) - } + if (this.opt.cache === false) + 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(); + } else if (this.opt.formType !== 'form') { + this.opt.param = JSON.stringify(this.opt.data); + } } //jsonp - if(this.opt.type === 'JSONP'){ - - 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) + if (this.opt.type === 'JSONP') { + 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); //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) + 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); } - }else{ - - this.xhr.onreadystatechange = function(ev){ - - if(_this.opt.timeout && _this.opt.timeout > 0){ - _this.opt['time' + this.readyState] = ev.timeStamp - if(this.readyState === 4){ - _this.opt.isTimeout = _this.opt.time4 - _this.opt.time1 > _this.opt.timeout + } else { + this.xhr.onreadystatechange = function(ev) { + if (_this.opt.timeout && _this.opt.timeout > 0) { + _this.opt['time' + this.readyState] = ev.timeStamp; + if (this.readyState === 4) { + _this.opt.isTimeout = + _this.opt.time4 - _this.opt.time1 > + _this.opt.timeout; } } - if(this.readyState !== 4){ - return + if (this.readyState !== 4) { + return; } - - _this.dispatch(_this.opt.isTimeout ? null : _this.xhr) - } - - + _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]) + for (var i in this.opt.headers) { + if (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){ + if (this.opt.timeout && this.opt.timeout > 0) { this.xhr.timeout = this.opt.timeout; } } - return this - - } - - - - - - - - - - - + return this.defer.promise; + }; // ---------------------- end ------------------------ - - if(!win.request){ + if (!win.request) { win.request = { - get: function(url){ - if(!url) - throw new Error('argument url is required') + get: function(url) { + 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') + post: function(url) { + 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') + jsonp: function(url) { + 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; +}); diff --git a/js/lib/request/promise.js b/js/lib/request/promise.js index 3d43065..2b15819 100644 --- a/js/lib/request/promise.js +++ b/js/lib/request/promise.js @@ -5,233 +5,219 @@ * */ -"use strict"; +'use strict'; -define(function(){ +define(function() { + var _Promise = function(callback) { + this.callback = []; + var _this = this; - var _Promise = function(callback){ - this.callback = [] - var _this = this + if (typeof this !== 'object') + throw new TypeError('Promises must be constructed via new'); - 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'); - if(typeof callback !== '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, _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) + _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) { + 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) + 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) + }, + 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] + resolve(val); + } + ); + }); + for (var i in _this) { + 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); + }; + + _Promise.race = function(arr) { + return _some(true, arr); + }; + + _Promise.defer = defer; + + // ----------------------------------------------------------- + + function _yes(val) { + return val; } - _Promise.all = function(arr){ - return _some(false, arr) + function _no(err) { + throw err; } - _Promise.race = function(arr){ - return _some(true, arr) + function done(callback) { + return this.then(callback, _no); } - _Promise.defer = defer - -// ----------------------------------------------------------- - - - - function _yes(val){ - return val + function fail(callback) { + return this.then(_yes, callback); } - function _no(err){ - throw err + function defer() { + var obj = {}; + obj.promise = new this(function(yes, no) { + obj.resolve = yes; + obj.reject = no; + }); + return obj; } - - 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 + 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) + 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 + function _reject(obj, val) { + 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' + 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) + 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; - function fireCallback(obj, callback){ - 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 : []; - function _some(bool, 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); - 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 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); } - }, function(val){ - end = true - no(val) - }) + ); } - for(var i = 0, len = iterable.length; i < len; i++){ - loop(iterable[i], i) + 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 + 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 - - -}) + return (window.Promise = nativePromise || _Promise); +});