方案
方案实际上是规定如何访问指定资源的主要标识符,它会告诉负责解析URL的应用程序应该使用什么协议,最常见的就是HTTP方案。 常见的方案格式:
http 超文本传输协议方案,默认端口为80
https 方案https和方案http是一对,为一个区别在于使用了网景的SSL,SSL为http提供了端到端的加密机制。默认端口为443
mailto 指向Email地址。
ftp 文件传输协议,可以用来从ftp服务器上传下载文件
file 访问本地文件
telnet 用于交互式访问业务
浏览器兼容性
在IE7以下版本的IE系列浏览器中,要应用AJAX必须使用ActiveXObject(这个对象是一个微软推广和支持在Internet Explorer中,不在Windows应用商店的应用程序。) 方法。
在标准浏览器(chrome、firefox、opera、safari、ie7+)当中则使用XMLHttpRequest对象。
如何发起AJAX?
在低版本IE(7-)中使用ActiveXObject构造AJAX对象时需要传入一个String类型的参数Microsoft.XMLHTTP,也可以使用Msxml3.XMLHTTP和Msxml2.XMLHTTP。
因为一开始是Microsoft.XMLHTTP 之后变成Msxml2.XMLHTTP及更新版的Msxml3.XMLHTTP。
在标准浏览器中则使用XMLHttpRequest对象
为了在项目中可以在任何浏览器中使用AJAX所以我们必须做一个判断,如果浏览器为低版本IE就使用ActiveXObject对象否则使用XMLHttpRequest对象。代码如下:
这样的话,我们就可以得到一个在任何浏览器都能发起AJAX的方法。但是这样左右一个坏处,就是每次获取AJAX对象时都会判断一次,这样做很费时费力。
所以,我们利用 → 惰性函数 ← 的概念来实现一个只需要第一次判断,后面都不需要判断的方法。
支持的AJAX对象放入一个function中,并且根据固定的顺序放到一个队列里。
for (var AJAXObj = [function () {
return new XMLHttpRequest
},function () {
return new ActiveXObject("Msxml2.XMLHTTP")
},function () {
return new ActiveXObject("Msxml3.XMLHTTP")
},function () {
return new ActiveXObject("Microsoft.XMLHTTP")
}],val = null,index = 0; index < AJAXObj.length; index++) {
//此方法的核心,如果当前浏览器支持此对象就用val保存起来,用保存当前最适合ajax对象的function替换XHR方法,并且结束该循环。
这样第二次执行XHR方法时就不需要循环,直接就能得到当前浏览器最适ajax对象。如果都不支持就抛出自定义引用错误。
try {
val = AJAXObj[index]()
} catch (b) {
continue
}
//假设当前浏览器为标准浏览器,此处执行完毕之后console.log(XHR);
//结果为:function () {
// return new XMLHttpRequest
//};XHR成功替换。
XHR=AJAXObj[index];
break
}
if (!val) {
throw new ReferenceError("XMLHttpRequest is not supported")
}
return val;
};
var xmlObj=XHR();
console.log(xmlObj);
本方法的核心就是利用 惰性函数 。这才是正点。第一次计算得到的值,供内部函数调用,然后用这个内部函数重置外部函数(因为同名),
以后就不用计算了,也不用判断分支条件。这时函数就相当于一个被赋值的变量。接下来我们依次介绍XMLHttpRequest和ActiveXObject如何使用。
使用XMLHttpRequest
XMLHttpRequest 是一个 JavaScript 对象,它最初由微软设计,随后被 Mozilla,Apple,和 Google采纳. 如今,该对象已经被 W3C组织标准化. 通过它,你可以很容易的取回一个URL上的资源数据. 尽管名字里有XML,但XMLHttpRequest 可以取回所有类型的数据资源,并不局限于XML. 而且除了HTTP,它还支持file 和 ftp 协议.
在浏览器中创建并使用一个 XMLHttpRequest 实例,可以使用如下语句:
XMLHttpRequest 让发送一个HTTP请求变得非常容易。你只需要简单的创建一个请求对象实例,打开一个URL,然后发送这个请求。当传输完毕后,结果的HTTP状态以及返回的响应内容也可以从请求对象中获取。本页把这个强大的JavaScript对象的一些常用的甚至略有晦涩的使用案例进行了一下概述。
XMLHttpRequest对象方法概述:
返回值 方法(参数)
1.void abort();中止操作
2.DOMString getAllResponseHeaders();得到所有响应头
3.DOMString? getResponseHeader(DOMString header);得到指定响应头
4.void open(DOMString method,DOMString url,optional boolean async,optional DOMString? user,optional DOMString? + password);开启XMLHttpRequest对象
5.void overrideMimeType(DOMString mime);重写MIME类型
6.void send();发送请求,此方法有六种重载
7.void send(ArrayBuffer data);发送二进制流
8.void send(Blob data);发送二进制块
9.void send(Document data);发送文档
10.void send(DOMString? data);发送字符串
411.void send(FormData data);发送格式化表单数据
12.void setRequestHeader(DOMString header,DOMString value);设置请求头
XMLHttpRequest对象属性概述:
属性名 格式类型 说明
onreadystatechange Function? 一个JavaScript函数对象,当readyState属性改变时会调用它。回调函数会在用户接口线程中调用。(警告: 不能在本地代码中使用. 也不应该在同步模式的请求中使用.)
readyState unsigned short 请求的五种状态: 0 UNSENT (未打开) open()方法还未被调用、 1 OPENED (未发送) send()方法还未被调用、2 HEADERS_RECEIVED (已获取响应头) send()方法已经被调用,响应头和响应状态已经返回、 3 、_LOADING (正在下载响应体) 响应体下载中; responseText中已经获取了部分数据、 4 DONE (请求完成) 整个请求过程已经完毕.
response varies 响应实体的类型由 responseType 来指定, 可以是 ArrayBuffer, Blob, Document, JavaScript 对象 (即 "json"), 或者是字符串。如果请求未完成或失败,则该值为 null。
responseText DOMString 此次请求的响应为文本,或是当请求未成功或还未发送时为 null。只读。
responseType XMLHttpRequestResponseType 设置该值能够改变响应类型。就是告诉服务器你期望的响应格式: "" (空字符串) 字符串(默认值)、 "ArrayBufferView" ArrayBufferView、 "blob" Blob、 "document" Document、 "json" JavaScript Object、 "text" 字符串。
responseXML Document? 本次请求的响应是一个 Document 对象,如果是以下情况则值为 null:请求未成功,请求未发送,或响应无法被解析成 XML 或 HTML。当响应为text/xml 流时会被解析。当 responseType 设置为"document",并且请求为异步的,则响应会被当做 text/html 流来解析。只读.(注意: 如果服务器不支持 text/xml Content-Type 头,你可以使用 overrideMimeType() 强制 XMLHttpRequest 将响应解析为 XML。)
status unsigned short 该请求的响应状态码 (例如,状态码200 表示一个成功的请求).只读.
statusText DOMString 该请求的响应状态信息,包含一个状态码和原因短语 (例如 "200 OK"). 只读.
upload XMLHttpRequestUpload 可以在 upload 上添加一个事件监听来跟踪上传过程。
withCredentials boolean 表明在进行跨站(cross-site)的访问控制(Access-Control)请求时,是否使用认证信息(例如cookie或授权的header)。 默认为 false。注意: 这不会影响同站(same-site)请求.
XMLHttpRequest和本地文件
网页中可以使用相对URL的能力通常意味着我们能使用本地文件系统来开发和测试HTML,并避免对web服务器进行不必要的部署。然后当使用XMLHttpRqeust进行Ajax编程时,这通常是不可行的。XMLHttpRequest用于HTTP和HTTPS协议一起工作。理论上,它能够同像FTP这样的其他协议一起工作,但比如像请求方法和响应状态码等部分API是HTTP特有的。如果从本地文件中加载网页,那么该网页中的脚本将无法通过相对URL使用XMLHttpRequest,因为这些URL将相对于file://URL而不是。而同源策略通常会阻止使用绝对。结果是当使用XMLHttpRequest时,为了测试它们通常必须把文件上传到wen服务器(或运行一个本地服务器)
方法
abort()
req.abort();
如果请求已经被发送,则立刻中止请求(cancel).abort()方法在所有的XMLHttpRequest版本和XHR2中可用,调用abort()方法在这个对象上触发abort事件。可以通过XMLHttpRequest对象的onabort属性是否存在来判断。
//if成立的话abort()存在,否则不存在
if('onabort' in req){
req.abort();
}
getAllResponseHeaders()
var allHeaders = req.getAllResponseHeaders();
返回所有响应头信息(响应头名和值),如果响应头还没接收,则返回null. (注意: 对于多部分请求,这将返回头从请求的当前一部分,而不是从原来的通道上。)
getResponseHeader()
var dateHeader = req.getAllResponseHeaders("Date");
返回指定的响应头的值,如果响应头还没被接受,或该响应头不存在,则返回null.
open()
注意: 调用此方法必须已经发出主动请求(open()或openRequest()已经被调用)是相当于调用abort()。
req.open(http Method,URL,isAsync,userName,password);
//参数
//http Method 请求所使用的HTTP方法; "POST" 或者 "GET". 如果下个参数是非HTTP(S)的URL,则忽略该参数.
//URL 该请求所要访问的URL
//isAsync 一个可选的布尔参数,默认为真,指示是否异步执行操作。如果该值为false时,send()方法不返回直到收到响应。如果为true,完成交易的通知使用事件侦听器提供。这必须是真实的,如果多部分属性为true,或将引发异常。
//userName 可选的用户名,以用于身份验证的目的;默认情况下,这是一个空字符串。
//password 可选的密码用于认证的目的;默认情况下,这是一个空字符串。
初始化一个请求. 该方法用于JavaScript代码中;如果是本地代码,使用 openRequest()方法代替.
如果传入的http method不区分大小写与 CONNECT,DELETE,GET,HEAD,OPTIONS,POST,PUT,TRACE,或者 TRACK匹配上,从范围0x61(ASCII a)每个字节0x7A(ASCII a)减去0x20。把小写转换成大写(如果它不匹配任何上述情况,它是通过传递字面上,包括在最后的请求。)
如果http method 不区分大小写匹配到 CONNECT,或者 TRACK 这三个方法,抛出 "SecurityError" 异常,因为安全风险已被明确禁止。旧浏览器并不支持所有这些方法,但至少HEAD得到广泛支持
overrideMimeType()
req.overrideMimeType("text/plain");
//参数必须为MIME Type格式
重写由服务器返回的MIME类型。这可以用于一下情况。假如你将下载XML文件,而你计划把它当成纯文本对待。可以使用overrideMimeType()让XMLHttpRequest知道它不需要把文件解析为XML文档:
//不要把响应作为XML文档处理
req.overrideMimeType('text/plain; charset=utf-8');
这个方法必须send()之前调用。
onload
req.onload=function(){
console.log(this.responseText,this.responseType,this.response);
}
当XMLHttpRequest对象加载完成时(readyState为4)触发。且只与readyState有关,与status和statustext无关。所以当注册onload的方法执行时不一定为成功的状态。只是也仅仅是这个条http事务完成而已。不注册此方法则onload默认为null。
onreadystatechange
req.onreadystatechange=function(){
//判断ajax成功,此写法有兼容性。
if(this.readyState==this.DONE&&this.statusText=="OK"){
console.log(this.response,'成功');
}
//判断ajax成功还有另外一种写法
if(this.readyState==4&&this.status==200){
console.log(this.responseText,'成功');
}
}
每当readyState的值改变时就会出发该方法。不注册此方法则onreadystatechange默认为null。
send()
注意: 所有相关的事件绑定必须在调用send()方法之前进行.
req.send(undefined||null||ArrayBufferView||Blob||XML||String||FormData);
//此方法有7种参数重载
发送请求. 如果该请求是异步模式(默认),该方法会立刻返回. 相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回.
GET请求绝对没有主体,所以应该传递null或者省略这个参数。POST请求通常拥有主体,同时它应该匹配使用setRequestHeader()指定的Content-Type头。
如果数据是一个Document,它在发送之前被序列化。当发送文件时,Firefox之前的版本3的版本总是使用UTF-8编码发送请求; Firefox 3的正常使用发送,如果没有指定编码由body.xml编码,或者UTF-8指定的编码文件。
setRequestHeader()
req.setRequestHeader("header","value");
//设置制定的请求头,此方法必须在send()执行之前执行。
//header 将要被赋值的请求头名称.
//value 给指定的请求头赋的值.
给指定的HTTP请求头赋值.在这之前,你必须确认已经调用 open() 方法打开了一个url.
如果对相同的头调用setRequestHeader()多次,新值不会取代之前指定的值,相反,HTTP请求将包含这个头的多个副本或者个头将指定多个值。例如:
req.setRequestHeader("Accepts",'text/html');
req.setRequestHeader("Accepts",'text/css');
//那个请求头中的Accepts的值为 “text/html,text/css”
你不能制定Content-Length、Date、Referer或User-Agent头,XMLHttpRequest将自动添加这些头而防止伪造他们。类似地,XMLHttpRequest对象自动处理cookie、连接时间、字符集和编码判断,所以你无法向setRequestHeader()传递这些头:
Accept-Charset
Content-Transfer-Encoding
Date
Connection
Expect
Content-Length
Host
Cookie
Keep-Alive
User-Agent
Cookie2
Referer
你能为请求指定Authorization头,但通常不需要这么做。如果请求一个受密码保护的URL,把用户名和密码作为第四个和第五个参数传递给open),则XMLHttpRequest将设置合适的头。
顺序问题
HTTP请求的各部分有指定顺序:请求方法和URL首先到达,然后是请求头,最后是请求主题。MXLHttpRequest实现通常直到调用send()方法才开始启动网络。
单XMLHttpRequest API的设计似乎使每个方法都将写入网络流。这意味着调用XMLHttpRequest方法的顺序必须匹配HTTP请求的架构。
例如,setRequestHeader()方法的调用必须在调用send()之前但在调用open()之后,否则它将抛出异常。
示例代码:
代码做一些与数据通过网络获取的XML文档
function processData(data) {
// taking care of data
}
function handler() {
if(this.readyState == this.DONE) {
if(this.status == 200 &&
this.responseXML != null &&
this.responseXML.getElementById('test').textContent) {
// success!
processData(this.responseXML.getElementById('test').textContent);
return;
}
// something went wrong
processData(null);
}
}
var client = new XMLHttpRequest();
client.onreadystatechange = handler;
client.open("GET","unicorn.xml");
client.send();
//如果你只是想记录一个消息服务器
function log(message) {
var client = new XMLHttpRequest();
client.open("POST","/log");
client.setRequestHeader("Content-Type","text/plain;charset=UTF-8");
client.send(message);
}
//或者,如果您要检查服务器上的文档的状态
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == this.DONE)
returnStatus(this.status);
}
client.open("HEAD",address);
client.send();
}
在低版本IE浏览器中使用ActiveXObject时需要注意的地方
使用ActiveXObject与XMLHttpRequest对象大体相同。不过还是有许多不同的地方。
不同点:
- ActiveXObject对象中没有timeout属性,没有ontimeout方法。
- ActiveXObject对象中不支持statustext属性。
- ActiveXObject对象中没有DONE、OPEN、UNSENT、HEADERS_RECEIVED、DONE 这些属性。
- ActiveXObject对象中没有onload方法。
- ActiveXObject对象中send()不支持ArrayBuffer|Blob|Formdata 等类型重载。
- ActiveXObject对象中没有withCredentials属性。
- 由于ActiveXObject对象只在IE5、IE6中使用,所以很多功能都没有。所以使用时需注意。
_ActiveXObject对象用法:
AJAX 实例
上面的基础知识和使用处理ajax的对象需要注意的一些地方我们都都已经提到了,现在我们开始写ajax示例,以便更好的巩固ajax知识。
这个示例是参照jQuery的ajax函数使用方法来编写的,并且可以使用链式调用以增强体验。
最终代码如下:
方法。
//每个方法都返回一个可供链式注册的对象。
//ajax()方法提供多个固定的参数以达到高配置性。
(function (global,undefined) {
//如果全局已经存在$http对象的话就直接返回,不执行任何代码。
if (global.$http) {
return
}
var http = global.$http = {};
//判断类型
function isType(str) {
return function (obj) {
return Object.prototype.toString.call(obj) == '[object ' + str + ']';
}
}
var isObject = isType("Object");
var isFunction = isType("Function");
var isNumber = isType("Number");
var isString = isType("String");
var isBoolean = isType('Boolean');
var isArray = isType('Array');
//检测参数中有没有`?`
var hasSearch = function (url) {
return /^.+\?[^?]*$/g.test(url)
};
//循环帮助<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>
var each=(function(){
if ([].forEach)
return function(arr,func){
[].forEach.call(arr,func);
}
else
return function(arr,func){
for (var i = 0; i < arr.length; i++) {
func.call(arr,arr[i],i,arr);
}
}
})();
//<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>ajax对象,var getXHR = function () {
for (var list = [function () {
return new XMLHttpRequest
},function () {
return new ActiveXObject("Microsoft.XMLHTTP")
},function () {
return new ActiveXObject("Msxml3.XMLHTTP")
}],temp = null,index = 0; index < list.length; index++) {
try {
temp = list[index]()
} catch (ex) {
continue
}
getXHR = list[index];
break;
}
if (!temp) {
throw new ReferenceError("browser is not supported")
}
return temp;
};
http.ajax = function (options) {
// 如果options不是一个对象那么此<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>后续将不执行。
if (!isObject(options)) return;
//默认参数对象
var defaultOptions = {
//<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" class="keywords">添加</a>到请求头`Accepts`中,用来说明这个Ajax接收什么MIME Type的数据。Array类型
accepts: undefined,//是否为异步,默认为true。Boolean类型
async: true,//在执行send()<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>之前<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank" class="keywords">调用</a>的<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>。Function类型
beforeSend: undefined,//是否缓存。Boolean类型
cache: false,//不管成功或失败都会执行的<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>。Function类型
complete: function () {},//<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" class="keywords">添加</a>到请求头`Content-Type`中,标识此http是什么MiME Type,默认为`application/x-www-form-urlencoded; charset=UTF-8`。String类型
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',//宿主对象。Object类型
context: undefined,//发送给服务器的数据。Object或者String类型
data: undefined,//服务器返回的数据格式,可以为`xml|bolb|arraybuffer|html|script|json|text`。String类型
dataType: 'text',//过滤服务器返回数据。Function类型
dataFilter: undefined,//执行失败、parseError或者timeout执行的<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>。Function类型
error: function (xhr,xhr.status,text) {},//<a href="https://www.jb51.cc/tag/zidingyi/" target="_blank" class="keywords">自定义</a>头信息。Object类型
headers: {},//重写服务器返回MIME Type。String类型
mimeType: '',//URL认证密码。String类型
password: undefined,//<a href="https://www.jb51.cc/tag/zhuce/" target="_blank" class="keywords">注册</a>对应http状态码时执行的<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>。Object类型
statusCode: {},//Ajax成功时执行的<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>。Function类型
success: function (response) {},//超时毫秒值,此值必须大于500毫秒,否则不生效。Number类型
timeout: undefined,//请求的http<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>,可以为`get|post|head|put|delete`。String类型
type: '',//请求的URL,此URL的方案不可以为`file`。String类型
url: '',//URL认证账号。String类型
username: undefined,//在send()执行前,通过此<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>操作xhr对象。Function类型
setXhrFields: function(xhr){}
},//临时变量
tempVal;
//覆盖默认参数对象
for (tempVal in defaultOptions) {
if (options.hasOwnProperty(tempVal) && options[tempVal])
defaultOptions[tempVal] = options[tempVal];
}
var xhr = getXHR(),_promise = new __promise();
if (!/^(get|post|head|put|delete)$/img.test(defaultOptions.type)) {
throw new ReferenceError('not supported this http method');
}
if (!/^(xml|bolb|arraybuffer|html|script|json|text)/img.test(defaultOptions.dataType)) {
throw new TypeError('not supported ' + defaultOptions.dataType + ' data type');
}
if (!isString(defaultOptions.url)) {
throw new TypeError('url must be a string')
}
//是否使用缓存,不使用则在URL后<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" class="keywords">添加</a>一个<a href="https://www.jb51.cc/tag/suiji/" target="_blank" class="keywords">随机</a>数
if (defaultOptions.cache) {
defaultOptions.url += (hasSearch(defaultOptions.url) ? '_=' : '?_=') + Math.random() * (1 << 24) | 0;
}
//将发送给服务器的数据从Object类型转为String类型
if (defaultOptions.data) {
if (isObject(defaultOptions.data)) {
var arr = [];
for (tempVal in defaultOptions.data) {
if (defaultOptions.data.hasOwnProperty(tempVal)) {
// 此处参见下文的表单操作
arr.push(encodeURIComponent(tempVal) + "=" + encodeURIComponent(defaultOptions.data[tempVal]));
}
}
defaultOptions.data = arr.join('&');
}
//当请求的http方法为get、head、delete中一个时直接拼接到URL后并且删除data。参见send()方法解释。
if (/^(get|head|delete)$/img.test(defaultOptions.type)) {
defaultOptions.url += (hasSearch(defaultOptions.url) ? '' : '?') + defaultOptions.data;
delete defaultOptions.data;
}
}
defaultOptions.setXhrFields(xhr);
xhr.open(defaultOptions.type,defaultOptions.url,defaultOptions.async,defaultOptions.username,defaultOptions.password);
if(isArray(defaultOptions.accepts)){
each(defaultOptions.accepts,function(x){
xhr.setRequestHeader('Accepts',x);
})
}
for (tempVal in defaultOptions.headers) {
if (defaultOptions.headers.hasOwnProperty(tempVal))
xhr.setRequestHeader(tempVal,defaultOptions.headers[tempVal]);
}
xhr.setRequestHeader("Content-Type",defaultOptions.contentType);
if (defaultOptions.context) {
//绑定宿主对象
defaultOptions.complete = defaultOptions.complete.bind(defaultOptions.context);
defaultOptions.success = defaultOptions.success.bind(defaultOptions.context);
defaultOptions.error = defaultOptions.error.bind(defaultOptions.context);
}
//将success、error、complete方法包裹起来
var _success = function (text) {
defaultOptions.success(text);
_promise._done(text);
defaultOptions.complete(xhr);
_promise._always();
},_error = function (text) {
defaultOptions.error(xhr,text);
_promise._fail(xhr,text);
defaultOptions.complete(xhr);
_promise._always();
};
//检测xhr对象是否有responseType,如果有则将dataType赋给它
('responseType' in xhr)&& (xhr.responseType = defaultOptions.dataType);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (defaultOptions.mimeType) {
//重写MIME Type
xhr.overrideMimeType(defaultOptions.mimeType);
}
//当http状态码为2xx时执行success,4xx或5xx时执行error
if (/^2\d{2}$/.test(this.status)) {
var returnVal = undefined;
if (xhr.responseType) {
returnVal = this.response;
} else {
//数据处理
switch (defaultOptions.dataType.toLowerCase()) {
case 'xml':
returnVal = this.responseXML;
break;
case 'html':
var frag = document.createDocumentFragment();
frag.innerHTML = this.responseText;
returnVal = frag;
break;
case 'script':
var scr = document.createElement("script");
scr.innerHTML = this.responseText;
returnVal = scr;
break;
case 'json':
if (global.JSON.parse) {
try {
returnVal = JSON.parse(this.responseText);
} catch (ex) {
_error(ex)
}
} else {
returnVal = eval('(' + this.responseText + ')');
}
break;
case 'arraybuffer':
throw new ReferenceError('not supported arraybuffer');
case 'blob':
throw new ReferenceError('not supported blob');
default:
returnVal = this.responseText;
}
}
_success(defaultOptions.dataFilter(returnVal)||returnVal);
}
if (/^(4|5)\d{2}$/.test(this.status)) {
_error();
}
//根据http状态码执行statusCode中对应的函数
(this.status.toString() in defaultOptions.statusCode) && defaultOptions.statusCode[this.status]();
}
};
if (defaultOptions.beforeSend) {
defaultOptions.beforeSend(xhr);
}
xhr.send(defaultOptions.data);
xhr.onerror = _error;
//超时设置,此方法有兼容性。所以执行前先做特性判断
if (isNumber(defaultOptions.timeout) && defaultOptions.timeout > 500) {
if ('timeout' in xhr) {
xhr.timeout = defaultOptions.timeout;
xhr.ontimeout = defaultOptions.error;
} else {
setTimeout(function () {
if (xhr.readyState != 4) {
_error();
}
},defaultOptions.timeout);
}
}
//返回链式<a href="https://www.jb51.cc/tag/zhuce/" target="_blank" class="keywords">注册</a>对象
return _promise;
};
//利用ajax<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>生产get、post<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>
each(['get','post'],function (x) {
http[x] = function (url,data,func,datatype) {
if (arguments.length != 4)
throw new TypeError('lacking arguments');
return http.ajax({
url: url,data: data,success: func,dataType: datatype,type: x
})
}
});
//利用ajax生产getScript<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>
http.getScript = function (url,func) {
return http.ajax({
url: url,type: 'get',dataType: 'script'
})
};
//链式<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank" class="keywords">调用</a>对象
function __promise() {
//设置默认<a href="https://www.jb51.cc/tag/hanshu/" target="_blank" class="keywords">函数</a>
this._done = this._fail = this._always = function () {
};
}
//这三个<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>执行完之后都必须将自己返回,否则无法链式<a href="https://www.jb51.cc/tag/zhuce/" target="_blank" class="keywords">注册</a>
__promise.prototype.done = function (func) {
this._done = func;
return this;
};
__promise.prototype.fail = function (func) {
this._fail = func;
return this;
};
__promise.prototype.always = function (func) {
this._always = func;
return this;
};
//AMD,CommonJs,then globals
if (typeof define === 'function' && define.amd) {
define([],function(){
return http;
});
} else if (typeof exports === 'object') {
module.exports = http;
} else {
global.$http = global.$http || http;
}
})(window);
如何调用上面的ajax库?
功能更加强大的函数
}