一、ajax简介
1、是asynchronous javascript and XML 的简写。翻译过来就是异步的javascript和XML,其中XML(Extensible Markup Language)是指可扩展标记语言,是标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
2、ajax这一技术能够向服务器请求额外的数据而无需卸载页面,会带来更好的用户体验。
3、ajax包含的步骤:
- 创建AJAX对象
- 发出HTTP请求
- 接收服务器传回的数据
- 更新网页的数据
总之就是ajax通过原生的XMLHttpRequest对象发出HTTP请求,得到服务器返回的数据后,再进行处理。
二、详解ajax的几个重要步骤
(一)创建ajax对象
ajax技术的核心是XMLHttpRequest对象(简称XHR)。创建一个XHR对象,因为XMLHttpRequest()是一个构造函数,所以也可以说是实例化一个XHR对象。下面就是创建XHR对象的兼容写法。
var xhr;
if(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
(二)发送请求
1、 open()
该方法接收三个参数:
xhr.open("get","example.php","false");
- open()方法第一个参数用于指定发送请求的方式,不区分大小写,通常使用大写字母。"GET"和"POST"是得到广泛支持的。该参数还可以是“HEAD”、“OPTIONS”、“PUT”。
- 第二个参数是URL,该URL相当于执行代码的当前页面,且只能向同一个域中使用相同协议和端口的URL发送请求。如果URL与启动请求的页面有任何差别,都会引起安全错误。
- 第三个参数是表示是否异步发送请求的布尔值,如果不填写,默认为true,表示异步发送。
- 如果请求一个受密码保护的URL,则将用于认证的用户名和密码作为第四个和第五个参数。
2、 send()
- 该方法接收一个参数,即要作为请求主体要发送的数据。调用send()方法后,请求会被分派到服务器
- 如果是“GET”方法,send()方法就无参数,或者参数为null。如果是“POST”方法,send()方法的参数则是数据。
xhr.open("GET","example.php","false");
xhr.send(null);
(三)接收响应
一个完整的HTTP响应由状态码、响应头集合和响应主体组成,这些都可以通过XHR对象的属性和方法使用。主要有以下四个属性:
- responseText:作为响应主体被返回的文本——文本的形式
- responseXML:当响应的内容类型是‘text/xml或者‘application/xml’时,该属性将保存着响应数据的XML—— DOM文档
- status:HTTP状态码——数字形式
- statusText:HTTP状态说明——文本形式
响应过程: 在接收到响应后,第一步是检查status属性,以确定响应已成功返回。status为200的时候表示成功返回,而此时responseText属性的内容已经就绪,而且内容类型正确的情况下responseXML也可以访问了。另外状态码status为304的时候表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本,也同时意味着响应是有效的。
无论内容类型是什么,响应主体的内容都会保存到responseText属性中,而对于非XML数据而言,responseXML属性的值将为null。
if((xhr.status >=200 && xhr.status<300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert("request was unsuccessful:" + xhr.status );
}
三、ajax的同步请求和异步请求
1、同步请求
如果接受的是同步响应,则需要将open()方法的第三个参数设置为false,那么send()将阻塞直到请求完成。一旦send()返回,仅需要检查XHR对象的status和responseText属性即可。
但是要尽量避免使用同步请求,因为客户端javascript是单线程的,当send()方法阻塞时,它通常会导致整个浏览器冻结。如果连接的服务器响应慢,那么用户的浏览器将冻结。
2、异步请求
如果需要接受的是异步响应,就需要检测XHR的readyState属性,该属性表示请求/响应过程中的当前活动阶段。该属性可取的值如下:
- 0(unset): 未初始化,尚未调用open()方法
- 1(opened): 启动。已经调用open()方法,尚未调用send()方法
- 2(headers_received): 发送。已经调用send()方法,且接收到头信息。
- 3(loading): 接收。已经接收到部分响应主体信息。
- 4(done): 完成。已经接收到全部响应数据,也可以在客户端使用了。
理论上只要readyState的属性值由一个值变成另一个值,都会触发一次readystatechange事件。所以可以利用这个事件来检测每次状态变化后readyState的值。但是我们只对readyState值为4的阶段感兴趣,因为这是所有数据已准备就绪。
注意:必须在调用open()方法之前指定readystatechange事件处理程序才能确保浏览器的兼容性,否则将无法接收到readyState值为0和1的情况。
//创建xhr对象
var xhr;
if(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接收响应
xhr.onreadystagechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//实际操作
result.innerHTML += xhr.responseText;
}
}
};
//发送请求
xhr.open("get","example.php",true);
xhr.send();//因为是“get”方式,所有send()没有参数
四、请求超时情况
XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。该属性默认为0,表示没有时间限制。该属性对应的是ontimeout事件,如果请求超时就会触发该事件。
xhr.open("post","example.php",true);
xhr.ontimeout = function(){
console.log('the request timed out');
};
xhr.timeout = 1000;
xhr.send(data);
五、GET和POST请求方式
1、GET
发送的数据:
- 使用GET方式发送数据时,数据被追加到open()方法中URL的末尾
- 数据以问号开始,名和值之间用等号链接,名值对之间用和号(&)分隔。
- 使用GET方式发送的数据常被称为查询字符串
xhr.open("GET","example.php?name_1=value_1&name_2=value_2",true);
编码情况:
因为URL无法识别特殊字符,所以当要发送的数据中包含特殊字符时(如中文),则需要使用编码方法进行编码。下面使用encodeURLComponent()方法进行编码:
var url = 'test.php' + '?name=' + encodeURIComponent('小倩');
xhr.open("GET",url,true);
可以看下URL被编码成了什么:
console.log(url);//test.php?name=%E5%B0%8F%E5%80%A9
编码函数:
可以构造一个函数向现有的URL的末尾添加查询字符串,这样的话就会更加方便,如下:
function addURLData(url,name,value) {
//先判断现有的URL中是否已经有数据链接在后面
url += (url.indexOf("?") == -1 ? "?" : "&");
//再拼接要添加的字符串
url += encodeURIComponent("name") + encodeURIComponent("value");
return url;
}
避免缓存:
再GET的请求中,为了避免缓存的影响,可以向URL中添加一个随机数或者时间戳。
xhr.open("GET",url + '&' +Math.random(),true);
或者
xhr.open("GET",url + '&' + Number(new Date()),true);
2、POST
POST请求应该把数据作为请求的主体提交,POST请求的主体可以包含非常多的数据,而且格式不限。在open()方法第一个参数位置传入“POST”,就可以初始化一个POST请求。
设置请求头:
- 发送POST请求的第二步就是向send()方法中传入某些数据。由于XHR最初的设计主要是为了处理XML,因此可以在此传入XML
DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串 - 默认情况下,服务器对POST请求和提交Web表单的请求并不会一视同仁。因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。不过,可以使用XHR来模仿表单提交:首先将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
如果不设置Content-Type,发送给服务器的数据就不会出现在 $ _POST超级全局变量中。这时要访问同样的数据,须借助$HTTP_RAW_POST_DATA
如果对相同的头调用多次setReQuestHeader(),新值不会取代之前指定的值。相反,HTTP请求将包含这个头的多个副本或这个头将指定多个值
发送主体:
下面是用send()方法发送数据。POST数据格式与查询字符串格式相同,如下:
xhr.send('name = "hxq" & num = 1997');
六、相应解码
1、我们从服务器接收到的响应主体类型可以是多种形式的,包括字符串String、ArrayBuffer对象、二进制Blob对象、JSON对象、javascirpt文件及表示XML文档的Document对象等。所以要针对不同的主体类型,进行相应的响应解码。
2、要进行解码就要了解XHR的相应属性:
- responseText:
responseText属性返回从服务器接收到的字符串,该属性为只读。如果本次请求没有成功或者数据不完整,该属性就会等于null。
如果服务器返回的数据格式是JSON、字符串、javascript或XML,都可以使用responseText属性 - response
response属性为只读,返回接收到的数据体。它的类型可以是ArrayBuffer、Blob、Document、JSON对象、或者一个字符串,这由XMLHttpRequest.responseType属性的值决定
如果本次请求没有成功或者数据不完整,该属性就会等于null.
IE-9不支持 - responseType
responseType属性用来指定服务器返回数据(xhr.response)的类型
“”:字符串(默认值) | “arraybuffer”:ArrayBuffer对象 |
---|---|
“blob”:Blob对象 | “document”:Document对象 |
“json”:JSON对象 | text”:字符串 |
- responseXML
responseXML属性返回从服务器接收到的Document对象,该属性为只读。如果本次请求没有成功,或者数据不完整,或者不能被解析为XML或HTML,该属性等于null - overrideMimeType()
该方法用来指定服务器返回数据的MIME类型。该方法必须在 send() 之前调用
传统上,如果希望从服务器取回二进制数据,就要使用这个方法,人为将数据类型伪装成文本数据
但是,这种方法很麻烦,在 XMLHttpRequest 版本升级以后,一般采用指定 responseType 的方法