本文实例讲述了JS XMLHttpRequest原理与使用方法。分享给大家供大家参考,具体如下:
你真的会使用XMLHttpRequest吗?
看到标题时,有些同学可能会想:“我已经用
xhr
成功地发过很多个Ajax
请求了,对它的基本操作已经算挺熟练了。” 我之前的想法和你们一样,直到最近我使用xhr
时踩了不少坑儿,我才突然发现其实自己并不够了解xhr
,我知道的只是最最基本的使用。
于是我决定好好地研究一番xhr
的真面目,可拜读了不少博客后都不甚满意,于是我决定认真阅读一遍W3C的XMLHttpRequest
标准。看完标准后我如同醍醐灌顶一般,感觉到了从未有过的清澈。这篇文章就是参考W3C的XMLHttpRequest
标准和结合一些实践验证总结而来的。
Ajax和XMLHttpRequest
我们通常将Ajax
等同于XMLHttpRequest
,但细究起来它们两个是属于不同维度的2个概念。
以下是我认为对
Ajax
较为准确的解释:(摘自what is Ajax)
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.AJAX is based on the following open standards:
Browser-based presentation using HTML and Cascading Style Sheets (CSS).
Data is stored in XML format and fetched from the server.
Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.
JavaScript to make everything happen.
从上面的解释中可以知道:ajax
是一种技术方案,但并不是一种新技术。它依赖的是现有的CSS
/HTML
/Javascript
,而其中最核心的依赖是浏览器提供的XMLHttpRequest
对象,是这个对象使得浏览器可以发出HTTP
请求与接收HTTP
响应。
所以我用一句话来总结两者的关系:我们使用XMLHttpRequest
对象来发送一个Ajax
请求。
XMLHttpRequest的发展历程
XMLHttpRequest
一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest
标准。XMLHttpRequest
标准又分为Level 1
和Level 2
。
XMLHttpRequest Level 1
主要存在以下缺点:
-
受同源策略的限制,不能发送跨域请求;
-
不能发送二进制文件(如图片、视频、音频等),只能发送纯文本数据;
-
在发送和获取数据的过程中,无法实时获取进度信息,只能判断是否完成;
那么Level 2
对Level 1
进行了改进,XMLHttpRequest Level 2
中新增了以下功能:
-
可以发送跨域请求,在服务端允许的情况下;
-
支持发送和接收二进制数据;
-
新增formData对象,支持发送表单数据;
-
发送和获取数据时,可以获取进度信息;
-
可以设置请求的超时时间;
当然更详细的对比介绍,可以参考阮老师的这篇文章,文章中对新增的功能都有具体代码示例。
XMLHttpRequest兼容性
关于xhr
的浏览器兼容性,大家可以直接查看“Can I use”这个网站提供的结果XMLHttpRequest兼容性,下面提供一个截图。
从图中可以看到:
-
IE8/IE9、Opera Mini 完全不支持
xhr
对象 -
IE10/IE11部分支持,不支持
xhr.responseType
为json
-
部分浏览器不支持设置请求超时,即无法使用
xhr.timeout
-
部分浏览器不支持
xhr.responseType
为blob
细说XMLHttpRequest如何使用
先来看一段使用XMLHttpRequest
发送Ajax
请求的简单示例代码。
function sendAjax() { //构造表单数据 var formData = new FormData(); formData.append('username', 'johndoe'); formData.append('id', 123456); //创建xhr对象 var xhr = new XMLHttpRequest(); //设置xhr请求的超时时间 xhr.timeout = 3000; //设置响应返回的数据格式 xhr.responseType = "text"; //创建一个 post 请求,采用异步 xhr.open('POST', '/server', true); //注册相关事件回调处理函数 xhr.onload = function(e) { if(this.status == 200||this.status == 304){ alert(this.responseText); } }; xhr.ontimeout = function(e) { ... }; xhr.onerror = function(e) { ... }; xhr.upload.onprogress = function(e) { ... }; //发送数据 xhr.send(formData); }
上面是一个使用xhr
发送表单数据的示例,整个流程可以参考注释。
接下来我将站在使用者的角度,以问题的形式介绍
xhr
的基本使用。
我对每一个问题涉及到的知识点都会进行比较细致地介绍,有些知识点可能是你平时忽略关注的。
如何设置request header
在发送Ajax
请求(实质是一个HTTP请求)时,我们可能需要设置一些请求头部信息,比如content-type
、connection
、cookie
、accept-xxx
等。xhr
提供了setRequestHeader
来允许我们修改请求 header。
void setRequestHeader(DOMString header, DOMString value);
注意点:
-
方法的第一个参数 header 大小写不敏感,即可以写成
content-type
,也可以写成Content-Type
,甚至写成content-Type
; -
Content-Type
的默认值与具体发送的数据类型有关,请参考本文【可以发送什么类型的数据】一节; -
setRequestHeader
必须在open()
方法之后,send()
方法之前调用,否则会抛错; -
setRequestHeader
可以调用多次,最终的值不会采用覆盖override
的方式,而是采用追加append
的方式。下面是一个示例代码:
var client = new XMLHttpRequest(); client.open('GET', 'demo.cgi'); client.setRequestHeader('X-Test', 'one'); client.setRequestHeader('X-Test', 'two'); // 最终request header中"X-Test"为: one, two client.send();
如何获取response header
xhr
提供了2个用来获取响应头部的方法:getAllResponseHeaders
和getResponseHeader
。前者是获取 response 中的所有header 字段,后者只是获取某个指定 header 字段的值。另外,getResponseHeader(header)
的header
参数不区分大小写。
DOMString getAllResponseHeaders();
DOMString getResponseHeader(DOMString header);
这2个方法看起来简单,但却处处是坑儿。
你是否遇到过下面的坑儿"XXX"
经过一番寻找最终在 Stack Overflow找到了答案。
-
原因1:W3C的 xhr 标准中做了限制,规定客户端无法获取 response 中的
Set-Cookie
、Set-Cookie2
这2个字段,无论是同域还是跨域请求; -
原因2:W3C 的 cors 标准对于跨域请求也做了限制,规定对于跨域请求,客户端允许获取的response header字段只限于“
simple response header
”和“Access-Control-Expose-Headers
” (两个名词的解释见下方)。
"
simple response header
"包括的 header 字段有:Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
;
"Access-Control-Expose-Headers
":首先得注意是"Access-Control-Expose-Headers
"进行跨域请求时响应头部中的一个字段,对于同域请求,响应头部是没有这个字段的。这个字段中列举的 header 字段就是服务器允许暴露给客户端访问的字段。
所以getAllResponseHeaders()
只能拿到限制以外(即被视为safe
)的header字段,而不是全部字段;而调用getResponseHeader(header)
方法时,header
参数必须是限制以外的header字段,否则调用就会报Refused to get unsafe header
的错误。
如何指定xhr.response的数据类型
有些时候我们希望xhr.response
返回的就是我们想要的数据类型。比如:响应返回的数据是纯JSON字符串,但我们期望最终通过xhr.response
拿到的直接就是一个 js 对象,我们该怎么实现呢?
有2种方法可以实现,一个是level 1
就提供的overrideMimeType()
方法,另一个是level 2
才提供的xhr.responseType
属性。
xhr.overrideMimeType()
overrideMimeType
是xhr level 1
就有的方法,所以浏览器兼容性良好。这个方法的作用就是用来重写response
的content-type
,这样做有什么意义呢?比如:server 端给客户端返回了一份document
或者是 xml
文档,我们希望最终通过xhr.response
拿到的就是一个DOM
对象,那么就可以用xhr.overrideMimeType('text/xml; charset = utf-8')
来实现。
再举一个使用场景,我们都知道xhr level 1
不支持直接传输blob二进制数据,那如果真要传输 blob 该怎么办呢?当时就是利用overrideMimeType
方法来解决这个问题的。
下面是一个获取图片文件的代码示例:
var xhr = new XMLHttpRequest(); //向 server 端获取一张图片 xhr.open('GET', '/path/to/image.png', true); // 这行是关键! //将响应数据按照纯文本格式来解析,字符集替换为用户自己定义的字符集 xhr.overrideMimeType('text/plain; charset=x-user-defined'); xhr.onreadystatechange = function(e) { if (this.readyState == 4 && this.status == 200) { //通过 responseText 来获取图片文件对应的二进制字符串 var binStr = this.responseText; //然后自己再想方法将逐个字节还原为二进制数据 for (var i = 0, len = binStr.length; i < len; ++i) { var c = binStr.charCodeAt(i); //String.fromCharCode(c & 0xff); var byte = c & 0xff; } } }; xhr.send();
代码示例中xhr
请求的是一张图片,通过将 response
的 content-type
改为'text/plain; charset=x-user-defined',使得 xhr
以纯文本格式来解析接收到的blob 数据,最终用户通过this.responseText
拿到的就是图片文件对应的二进制字符串,最后再将其转换为 blob 数据。
xhr.responseType
responseType
是xhr level 2
新增的属性,用来指定xhr.response
的数据类型,目前还存在些兼容性问题,可以参考本文的【XMLHttpRequest
的兼容性】这一小节。那么responseType
可以设置为哪些格式呢,我简单做了一个表,如下:
xhr.response
数据类型""
String
字符串
默认值(在不设置responseType
时)
"text"
String
字符串
"document"
Document
对象
希望返回 XML
格式数据时使用
"json"
javascript
对象
存在兼容性问题,IE10/IE11不支持
"blob"
Blob
对象
"arrayBuffer"
ArrayBuffer
对象
下面是同样是获取一张图片的代码示例,相比xhr.overrideMimeType
,用xhr.response
来实现简单得多。
var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/image.png', true); //可以将`xhr.responseType`设置为`"blob"`也可以设置为`" arrayBuffer"` //xhr.responseType = 'arrayBuffer'; xhr.responseType = 'blob'; xhr.onload = function(e) { if (this.status == 200) { var blob = this.response; ... } }; xhr.send();
小结
虽然在xhr level 2
中,2者是共同存在的。但其实不难发现,xhr.responseType
就是用来取代xhr.overrideMimeType()
的,xhr.responseType
功能强大的多,xhr.overrideMimeType()
能做到的xhr.responseType
都能做到。所以我们现在完全可以摒弃使用xhr.overrideMimeType()
了。
如何获取response数据
xhr
提供了3个属性来获取请求返回的数据,分别是:xhr.response
、xhr.responseText
、xhr.responseXML
-
xhr.response
-
默认值:空字符串
""
-
当请求完成时,此属性才有正确的值
-
请求未完成时,此属性的值可能是
""
或者null
,具体与xhr.responseType
有关:当responseType
为""
或"text"
时,值为""
;responseType
为其他值时,值为null
-
-
xhr.responseText
-
默认值为空字符串
""
-
只有当
responseType
为"text"
、""
时,xhr
对象上才有此属性,此时才能调用xhr.responseText
,否则抛错 -
只有当请求成功时,才能拿到正确值。以下2种情况下值都为空字符串
""
:请求未完成、请求失败
-
-
xhr.responseXML
-
默认值为
null
-
只有当
responseType
为"text"
、""
、"document"
时,xhr
对象上才有此属性,此时才能调用xhr.responseXML
,否则抛错 -
只有当请求成功且返回数据被正确解析时,才能拿到正确值。以下3种情况下值都为
null
:请求未完成、请求失败、请求成功但返回数据无法被正确解析时
-
如何追踪ajax请求的当前状态
在发一个ajax
请求后,如果想追踪请求当前处于哪种状态,该怎么做呢?
用xhr.readyState
这个属性即可追踪到。这个属性是只读属性,总共有5种可能值,分别对应xhr
不同的不同阶段。每次xhr.readyState
的值发生变化时,都会触发xhr.onreadystatechange
事件,我们可以在这个事件中进行相关状态判断。
xhr.onreadystatechange = function () { switch(xhr.readyState){ case 1://OPENED //do something break; case 2://HEADERS_RECEIVED //do something break; case 3://LOADING //do something break; case 4://DONE //do something break; }
0
UNSENT
(初始状态,未打开)
此时xhr
对象被成功构造,open()
方法还未被调用
1
OPENED
(已打开,未发送)
open()
方法已被成功调用,send()
方法还未被调用。注意:只有xhr
处于OPENED
状态,才能调用xhr.setRequestHeader()
和xhr.send()
,否则会报错
2
HEADERS_RECEIVED
(已获取响应头)
send()
方法已经被调用, 响应头和响应状态已经返回
3
LOADING
(正在下载响应体)
响应体(response entity body
)正在下载中,此状态下通过xhr.response
可能已经有了响应数据
4
DONE
(整个数据传输过程结束)
整个数据传输过程结束,不管本次请求是成功还是失败
如何设置请求的超时时间
如果请求过了很久还没有成功,为了不会白白占用的网络资源,我们一般会主动终止请求。XMLHttpRequest
提供了timeout
属性来允许设置请求的超时时间。
xhr.timeout
单位:milliseconds 毫秒
默认值:0
,即不设置超时
很多同学都知道:从请求开始 算起,若超过 timeout
时间请求还没有结束(包括成功/失败),则会触发ontimeout事件,主动结束该请求。
【那么到底什么时候才算是请求开始 ?】
——xhr.onloadstart
事件触发的时候,也就是你调用xhr.send()
方法的时候。
因为xhr.open()
只是创建了一个连接,但并没有真正开始数据的传输,而xhr.send()
才是真正开始了数据的传输过程。只有调用了xhr.send()
,才会触发xhr.onloadstart
。
【那么什么时候才算是请求结束 ?】
—— xhr.loadend
事件触发的时候。
另外,还有2个需要注意的坑儿:
-
可以在
send()
之后再设置此xhr.timeout
,但计时起始点仍为调用xhr.send()
方法的时刻。 -
当
xhr
为一个sync
同步请求时,xhr.timeout
必须置为0
,否则会抛错。原因可以参考本文的【如何发一个同步请求】一节。
如何发一个同步请求
xhr
默认发的是异步请求,但也支持发同步请求(当然实际开发中应该尽量避免使用)。到底是异步还是同步请求,由xhr.open()
传入的async
参数决定。
open(method, url [, async = true [, username = null [, password = null]]])
-
method
: 请求的方式,如GET/POST/HEADER
等,这个参数不区分大小写 -
url
: 请求的地址,可以是相对地址如example.php
,这个相对是相对于当前网页的url
路径;也可以是绝对地址如http://www.example.com/example.php
-
async
: 默认值为true
,即为异步请求,若async=false
,则为同步请求
在我认真研读W3C 的 xhr 标准前,我总以为同步请求和异步请求只是阻塞和非阻塞的区别,其他什么事件触发、参数设置应该是一样的,事实证明我错了。
W3C 的 xhr标准中关于open()
方法有这样一段说明:
Throws an "InvalidAccessError" exception if async is false, the JavaScript global environment is a document environment, and either the timeout attribute is not zero, the withCredentials attribute is true, or the responseType attribute is not the empty string.
从上面一段说明可以知道,当xhr
为同步请求时,有如下限制:
-
xhr.timeout
必须为0
-
xhr.withCredentials
必须为false
-
xhr.responseType
必须为""
(注意置为"text"
也不允许)
若上面任何一个限制不满足,都会抛错,而对于异步请求,则没有这些参数设置上的限制。
之前说过页面中应该尽量避免使用sync
同步请求,为什么呢?
因为我们无法设置请求超时时间(xhr.timeout
为0
,即不限时)。在不限制超时的情况下,有可能同步请求一直处于pending
状态,服务端迟迟不返回响应,这样整个页面就会一直阻塞,无法响应用户的其他交互。
另外,标准中并没有提及同步请求时事件触发的限制,但实际开发中我确实遇到过部分应该触发的事件并没有触发的现象。如在 chrome中,当xhr
为同步请求时,在xhr.readyState
由2
变成3
时,并不会触发 onreadystatechange
事件,xhr.upload.onprogress
和 xhr.onprogress
事件也不会触发。
如何获取上传、下载的进度
在上传或者下载比较大的文件时,实时显示当前的上传、下载进度是很普遍的产品需求。
我们可以通过onprogress
事件来实时显示进度,默认情况下这个事件每50ms触发一次。需要注意的是,上传过程和下载过程触发的是不同对象的onprogress
事件:
-
上传触发的是
xhr.upload
对象的onprogress
事件 -
下载触发的是
xhr
对象的onprogress
事件
xhr.onprogress = updateProgress; xhr.upload.onprogress = updateProgress; function updateProgress(event) { if (event.lengthComputable) { var completedPercent = event.loaded / event.total; } }
可以发送什么类型的数据
void send(data);
xhr.send(data)
的参数data可以是以下几种类型:
-
ArrayBuffer
-
Blob
-
Document
-
DOMString
-
FormData
-
null
如果是 GET/HEAD请求,send()
方法一般不传参或传 null
。不过即使你真传入了参数,参数也最终被忽略,xhr.send(data)
中的data会被置为 null
.
xhr.send(data)
中data参数的数据类型会影响请求头部content-type
的默认值:
-
如果
data
是Document
类型,同时也是HTML Document
类型,则content-type
默认值为text/html;charset=UTF-8
;否则为application/xml;charset=UTF-8
; -
如果
data
是DOMString
类型,content-type
默认值为text/plain;charset=UTF-8
; -
如果
data
是FormData
类型,content-type
默认值为multipart/form-data; boundary=[xxx]
-
如果
data
是其他类型,则不会设置content-type
的默认值
当然这些只是content-type
的默认值,但如果用xhr.setRequestHeader()
手动设置了中content-type
的值,以上默认值就会被覆盖。
另外需要注意的是,若在断网状态下调用xhr.send(data)
方法,则会抛错:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'
。一旦程序抛出错误,如果不 catch 就无法继续执行后面的代码,所以调用 xhr.send(data)
方法时,应该用 try-catch
捕捉错误。
try{ xhr.send(data) }catch(e) { //doSomething... };
xhr.withCredentials与 CORS 什么关系
我们都知道,在发同域请求时,浏览器会将
cookie
自动加在request header
中。但大家是否遇到过这样的场景:在发送跨域请求时,cookie
并没有自动加在request header
中。
造成这个问题的原因是:在CORS
标准中做了规定,默认情况下,浏览器在发送跨域请求时,不能发送任何认证信息(credentials
)如"cookies
"和"HTTP authentication schemes
"。除非xhr.withCredentials
为true
(xhr
对象有一个属性叫withCredentials
,默认值为false
)。
所以根本原因是cookies
也是一种认证信息,在跨域请求中,client
端必须手动设置xhr.withCredentials=true
,且server
端也必须允许request
能携带认证信息(即response header
中包含Access-Control-Allow-Credentials:true
),这样浏览器才会自动将cookie
加在request header
中。
另外,要特别注意一点,一旦跨域request
能够携带认证信息,server
端一定不能将Access-Control-Allow-Origin
设置为*
,而必须设置为请求页面的域名。
xhr相关事件
事件分类
xhr
相关事件有很多,有时记起来还挺容易混乱。但当我了解了具体代码实现后,就容易理清楚了。下面是XMLHttpRequest
的部分实现代码:
interface XMLHttpRequestEventTarget : EventTarget { // event handlers attribute EventHandler onloadstart; attribute EventHandler onprogress; attribute EventHandler onabort; attribute EventHandler onerror; attribute EventHandler onload; attribute EventHandler ontimeout; attribute EventHandler onloadend; }; interface XMLHttpRequestUpload : XMLHttpRequestEventTarget { }; interface XMLHttpRequest : XMLHttpRequestEventTarget { // event handler attribute EventHandler onreadystatechange; readonly attribute XMLHttpRequestUpload upload; };
从代码中我们可以看出:
-
XMLHttpRequestEventTarget
接口定义了7个事件:-
onloadstart
-
onprogress
-
onabort
-
ontimeout
-
onerror
-
onload
-
onloadend
-
-
每一个
XMLHttpRequest
里面都有一个upload
属性,而upload
是一个XMLHttpRequestUpload
对象 -
XMLHttpRequest
和XMLHttpRequestUpload
都继承了同一个XMLHttpRequestEventTarget
接口,所以xhr
和xhr.upload
都有第一条列举的7个事件 -
onreadystatechange
是XMLHttpRequest
独有的事件
所以这么一看就很清晰了:
xhr
一共有8个相关事件:7个XMLHttpRequestEventTarget
事件+1个独有的onreadystatechange
事件;而xhr.upload
只有7个XMLHttpRequestEventTarget
事件。
事件触发条件
下面是我自己整理的一张xhr
相关事件触发条件表,其中最需要注意的是 onerror
事件的触发条件。
onreadystatechange
每当xhr.readyState
改变时触发;但xhr.readyState
由非0
值变为0
时不触发。
onloadstart
调用xhr.send()
方法后立即触发,若xhr.send()
未被调用则不会触发此事件。
onprogress
xhr.upload.onprogress
在上传阶段(即xhr.send()
之后,xhr.readystate=2
之前)触发,每50ms触发一次;xhr.onprogress
在下载阶段(即xhr.readystate=3
时)触发,每50ms触发一次。
onload
当请求成功完成时触发,此时xhr.readystate=4
onloadend
当请求结束(包括请求成功和请求失败)时触发
onabort
当调用xhr.abort()
后触发
ontimeout
xhr.timeout
不等于0,由请求开始即onloadstart
开始算起,当到达xhr.timeout
所设置时间请求还未结束即onloadend
,则触发此事件。
onerror
在请求过程中,若发生Network error
则会触发此事件(若发生Network error
时,上传还没有结束,则会先触发xhr.upload.onerror
,再触发xhr.onerror
;若发生Network error
时,上传已经结束,则只会触发xhr.onerror
)。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode
是4xx
时,并不属于Network error
,所以不会触发onerror
事件,而是会触发onload
事件。
事件触发顺序
当请求一切正常时,相关的事件触发顺序如下:
-
触发
xhr.onreadystatechange
(之后每次readyState
变化时,都会触发一次) -
触发
xhr.onloadstart
//上传阶段开始: -
触发
xhr.upload.onloadstart
-
触发
xhr.upload.onprogress
-
触发
xhr.upload.onload
-
触发
xhr.upload.onloadend
//上传结束,下载阶段开始: -
触发
xhr.onprogress
-
触发
xhr.onload
-
触发
xhr.onloadend
发生abort/timeout/error异常的处理
在请求的过程中,有可能发生 abort
/timeout
/error
这3种异常。那么一旦发生这些异常,xhr
后续会进行哪些处理呢?后续处理如下:
-
一旦发生
abort
或timeout
或error
异常,先立即中止当前请求 -
将
readystate
置为4
,并触发xhr.onreadystatechange
事件 -
如果上传阶段还没有结束,则依次触发以下事件:
-
xhr.upload.onprogress
-
xhr.upload.[onabort或ontimeout或onerror]
-
xhr.upload.onloadend
-
-
触发
xhr.onprogress
事件 -
触发
xhr.[onabort或ontimeout或onerror]
事件 -
触发
xhr.onloadend
事件
在哪个xhr事件中注册成功回调?
从上面介绍的事件中,可以知道若xhr
请求成功,就会触发xhr.onreadystatechange
和xhr.onload
两个事件。 那么我们到底要将成功回调注册在哪个事件中呢?我倾向于 xhr.onload
事件,因为xhr.onreadystatechange
是每次xhr.readyState
变化时都会触发,而不是xhr.readyState=4
时才触发。
xhr.onload = function () { //如果请求成功 if(xhr.status == 200){ //do successCallback } }
上面的示例代码是很常见的写法:先判断http
状态码是否是200
,如果是,则认为请求是成功的,接着执行成功回调。这样的判断是有坑儿的,比如当返回的http
状态码不是200
,而是201
时,请求虽然也是成功的,但并没有执行成功回调逻辑。所以更靠谱的判断方法应该是:当http
状态码为2xx
或304
时才认为成功。
xhr.onload = function () { //如果请求成功 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ //do successCallback } }
结语
终于写完了......
看完那一篇长长的W3C的xhr 标准,我眼睛都花了......
希望这篇总结能帮助刚开始接触XMLHttpRequest
的你。
最后给点扩展学习资料,如果你:
-
想真正搞懂
XMLHttpRequest
,最靠谱的方法还是看 W3C的xhr 标准; -
想结合代码学习如何用
XMLHttpRequest
发各种类型的数据,可以参考html5rocks上的这篇文章 -
想粗略的了解
XMLHttpRequest
的基本使用,可以参考MDN的XMLHttpRequest介绍; -
想了解
XMLHttpRequest
的发展历程,可以参考阮老师的文章; -
想了解
Ajax
的基本介绍,可以参考AJAX Tutorial; -
想了解跨域请求,则可以参考W3C的 cors 标准;
-
想了解
http
协议,则可以参考HTTP Tutorial;
更多关于ajax相关内容感兴趣的读者可查看本站专题:《jquery中Ajax用法总结》、《JavaScript中ajax操作技巧总结》、《PHP+ajax技巧与应用小结》及《asp.net ajax技巧总结专题》
希望本文所述对大家ajax程序设计有所帮助。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]