Ajax高级笔记 JavaScript高级程序设计笔记
Ajax通信与数据格式无关,从服务器获取的数据不一定是XML数据。
Ajax的核心:XMLHttpRequest对象(简称XHR)
在XHR对象之前,Ajax通信通常使用hack手段,如使用隐藏的或内嵌的框架。
XHR对象为向服务器发送信息和解析服务器响应提供了流畅的接口。
1.XMLHttpRequest对象
IE5是第一款引进XHR对象的浏览器,通过MSXML库中的ActiveX对象实现(有3个版本)。
兼容所有浏览器,创建XHR对象:
functioncreateXHR(){ if(typeofXMLHttpRequest!="undefined"){ returnnewXMLHttpRequest(); }elseif(typeofActiveXObject!="undefined"){ if(typeofarguments.callee.activeXString!="string"){ varversions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i,len; for(i=0,len=versions.length;i之后就能在所有浏览器创建XHR对象:varxhr=createrXHR();
2.原生XHR对象(支持的浏览器:IE7+、FF、Chrome、Opera、Safari)
通过XMLHttpRequest构建函数,创建XHR对象:
varxhr=newXMLHttpRequest();3.XHR用法
3-1.open()
open()3个参数:发送的类型、请求的URL、表是否异步的布尔值
xhr.open("get","example.php",false);①URl为相对于执行代码的当前页,或绝对地址;
②false为同步,JavaScript代码会在服务器响应后再继续执行;
③调用open()只是启动一个请求以备发送,还没真正发送;
④只能在同个域中使用相同端口和协议的URL发送请求。
3-2.send()
send()1个参数:请求主体发送的数据,不需要通过请求主体发送数据则传入null。
调用send()后,请求被分派到服务器。
xhr.open("get","example.php",false); xhr.send(null);3-3.收到响应后,响应数据会自动填充XHR对象的属性:
responseText:作为响应的主体被返回的文本;
responseXML:若响应的内容类型”text/xml”或”application/xml”,此属性保存响应数据XMLDOM文档
status:响应的HTTP状态;
statusText:HTTP状态的说明。
☆:无论什么内容类型,响应主体的内容都会保存在responseText属性中。对于非XML数据,responseXML属性值为null。
3-4.status属性确认响应是否成功返回HTTP状态代码:
200:响应有效,responseText属性已就绪,内容类型正确下的responseXML也可访问。
304:响应有效,只是请求的资源并为修改,可直接使用浏览器中缓存的版本。
正确检查上述2种状态代码:
status判断
if((xhr.status>=200&&xhr.status<=300)||xhr.status==304){ alert(xhr.responseText); }else{ alert("Requestwasunsuccessful:"+xhr.status); };3-5.readystate属性
该属性存储请求/响应过程的当前活动状态。
0:未初始化,未调用open();
1:启动,调用了open();
2:发送,调用了send(),未接受响应;
3:接受,已接受部分响应;
4:完成,已接受全部响应,且可在客户端使用。3-6.readystatechange事件
该事件,在readystate属性值改变时触发。
readystatechange事件句柄
varxhr=createXHR(); xhr.onreadystatechange=function(event){ if(xhr.readyState==4){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else{ alert("Requestwasunsuccessful:"+xhr.status); } } }; xhr.open("get","example.txt",true); xhr.send(null);①必须在调用open()之前知道readystatechange事件的事件处理程序,确保兼容。
②该事件处理程序中没有传递event对象,必须通过XHR对象本地来确定下一步怎么做;
③使用xhr对象而不使用this对象,是因为onreadystatechange事件处理程序的作用域问题。使用this对象在一些浏览器会导致函数执行失败或发生错误。
3-7.abort()
调用此方法可取消异步请求:xhr.abort();
调用后,xhr对象停止触发事件,不允许访问如何与响应相关的属性;
终止请求后,应对XHR对象进行解引用操作,不建议重用XHR对象。
4、HTTP头部信息
发送请求时的头部信息:
Accept:浏览器能够处理的内容类型
Accept-Charset:浏览器能够显示的字符集
Accept-Encoding:浏览器能够处理的压缩编码
Axxept-Language:浏览器当前设置的语言
Connection:浏览器与服务器之间连接的类型
Cookie:当前页面设置的如何Cookie
Host:发送请求耳洞页面所在域
Referer:发出请求的页面的URI
User-Agent:浏览器的用户代理字符串
setRequestHeader()
设置自定义头部信息。
2个参数:头部字段名称、头部信息值。
需在open()方法之后调用send()之前调用setRequestHeader(),才能成功发送请求头部信息。
自定义HTTP头部信息
varxhr=createXHR(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else{ alert("Requestwasunsuccessful:"+xhr.status); } } }; xhr.open("get","example.php",true); xhr.setRequestHeader("MyHeader","MyValue"); xhr.send(null);getRequestHeader()
获取指定的相应头部信息
xhr.getRequestHeader(“MyHeader”); getAllRequestHeader()获取一个包含所有头部信息的长字符串
xhr.getAllRequestHeader();
5、GET请求
对于XHR对象,位于opne()的URL末尾的查询字符串需经过编码,使用encodeURIComponent()编码。
名-值对需用和号(&)分隔。
自定义函数,添加URL查询字符串参数:
functionaddURLParam(url,name,value){ url+=(url.indexOf('?')==-1?'?':'&'); url+=encodeURIComponent(name)+'='+encodeURIComponent(value); returnurl; }6、POST请求
长用于想服务器发送要保存的数据。
由于XHR其初的设计是为了处理XML,故在send(0中可传入XHRDOM文档。
6-1.服务端读取POST数据
①默认情况下,服务器对POST请求和提交Web表单不会一视同仁,故服务端需要程序来读取发送的原始数据,并解析出有用部分。
②XHR模拟表单提交:
1.将Content-Type头部信息设置为application/x-www-form-urlencoded(即表单提交时的内容问题);
2.以适当格式创建一个字符串。(通过serialize()函数创建该字符串,序列化表单数据)
XHR模拟表单提交
functionsubmitData(){ varxhr=createXHR(); xhr.onreadystatechange=function(event){ if(xhr.readyState==4){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else{ alert("Requestwasunsuccessful:"+xhr.status); } } }; xhr.open("post","postexample.php",true); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); varform=document.getElementById("user-info"); xhr.send(serialize(form)); }7、CORS跨源资源共享(IE8+、FF、Chrome....)
跨域安全策略限制了Ajax的异步通信,CORS则是定义了跨域时,客户端和服务器的沟通。
CORS思想:使用自定义HTTP头部让浏览器与服务器进行沟通,从而决定请求/响应的成功与否。
7-1.给一个请求附加Origin头部,包含请求页面的源信息(协议、域名和端口)
Origin:http://www.domain.com服务器根据Origin判断是否接收请求,接收则在Access-Control-Allow-Origin头部会发相同信息。
(若是公共资源,可以回发"*")
Access-Control-Allow-Origin:http://www.domain.com
若无此头部或头部信息不匹配,浏览器将驳回请求。
☆请求和响应不会包含cookie信息。
7-2.IE8+对CORS的实现
IE8引入的XDR(XDomainRequest)类型,类型XHR,可实现安全可靠的跨域通信。
7-2-1.XDR与XHR的不同之处:
①cookie不会随请求发送,也不会随响应返回;
②只能设置请求头部信息中的Content-Type字段;
③不能访问响应头部信息;
④只支持GET和POST请求
XDR缓解了CSRF(跨站请求伪造)和XSS(跨站点脚本)问题
被请求的资源可判断用户代理、来源页面等如何数据来决定是否设置Access-Control-Allow-Origin头部
7-2-2.XDR使用方法类似XHR,创建一个XDomainRequest实例,调用open(),再调用send()。
XDR只能执行异步请求,所以open()方法只有两个参数,请求的类型和URL。
在收到响应后,只能访问响应的原始文本,无法确定响应的状态代码。
只要响应有效就会触发load事件,响应的数据会保存在responseText属性中。
如果失败(如,响应中缺少Access-Control-Allow-Origin头部)就会触发error事件,但该事件无有用信息,需要自定义一个onerror事件句柄。
obload事件-onerror事件
varxdr=newXDomainRequest(); xdr.onload=function(){ alert(xdr.responseText); }; xdr.onerror=function(){ alert("Error!"); }; xdr.open("get","http://www.somewhere-else.com/xdr.php"); xdr.send(null);在请求返回前调用abort()可终止请求。
7-2-3.XDR也支持timeout属性及ontiomout事件处理程序,在运行超过timeout设定的秒数后,调用ontimeout事件句柄。
为支持POST请求,XDR提供了contentType属性,用于表示发送数据的格式。
contentType属性是XDR对象影响头部信息的唯一方式。
xdr.contentType="application/x-www-form-urlencoded";7-3其他浏览器对CORS的实现
FF等浏览器都通过XMLHttpRequest对象实现了对CORS的原生支持。要请求另一个域中的资源时,使用标准XHR对象并在open()中传入绝对URL即可。
标准XHR的跨域
varxhr=createXHR(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else{ alert("Requestwasunsuccessful:"+xhr.status); } } }; xhr.open("get","http://www.abc.com/page/",true); xhr.send(null);与IE不同,通过跨域XHR对象可以访问status属性和statusText属性,也可同步请求。
7-3-1.跨域XHR的限制:
①不能使用setRequestHeader()设置自定义头部;
②不能发送和接收cookie;
③调用getAllResponseHeader()方法总会返回空字符串。
7-3-2.无论同源请求还是跨域请求都是使用相同的接口,故对于本地资源,最好用相对URL,对远程资源再用绝对URL。
这样能消除歧义,避免出现限制访问头部或本地cookie信息等问题。
7-4、跨浏览器的CORS(IE8+、FF等)
检测XHR是否支持CORS的方法:检查是否存在withCredentials属性,在结合检测XDomainRequest对象是否存在。
CORS跨域兼容
functioncreateCORSRequest(method,url){ varxhr=newXMLHttpRequest(); if("withCredentials"inxhr){ xhr.open(method,url,true); }elseif(typeofXDomainRequest!="undefined"){ xhr=newXDomainRequest(); xhr.open(method,url); }else{ xhr=null; } returnxhr; } varrequest=createCORSRequest("get","http://www.somewhere-else.com/xdr.php"); if(request){ request.onload=function(){ //dosomethingwithrequest.responseText }; request.send(); }上述createCORSRequest()函数返回的对象的属性(XHR和XDR的共同属性):
①abort():停止正在进行的请求;
②onerror:用于替代onreadystatechange检测错误;
③onload:用于代替onreadystatechange检测成功;
④responseText:用于取得响应内容;
⑤send():用于发送请求。
8、其他跨域技术
在CORS出现前,常利用DOM中能够执行跨域请求的功能,在不依赖XHR对象时,也能发送某种请求。
与COSR不同的是,不用修改服务器代码。
8-1.图像Ping
使用标签,由于可以从任何网页加载图像,故常是在线广告跟踪浏览量的只要方式。
可动态创建图像,使用它们的onload和onerror事件句柄,确定是否接受到了响应。
varimg=newImage(); img.onload=img.onerror=function(){ alert("Done!"); }; img.src="http://www.example.com/test?name=Nicholas";图像Ping是与服务器进行简单、单向的跨域通信的一种方式。请求的数据通过查询字符串形式发送,响应可以是任何内容,通常是像素图或204响应。虽然通过图像Ping,浏览器得不到任何具体数据,但通过侦听load和error事件,能找到响应收到的时间。
图像Ping常用于跟踪用户点击页面或动态广告曝光次数。
缺点:①只能发送GET请求;②无法访问服务器响应文本。
8-2.JSONP
JSONP(JSONwidthPadding)填充式JSON或参数式JSON,类似JSON,是包含在函数调用中的JSON:
callback({"name":"value"});
8-2-1.JSONP有两个部分:回调函数和数据回调函数:当响应到来时应该在页面中调用的函数。回调函数的名称在请求中指定。
数据:传入回调函数的JSON数据。
8-2-2.JSONP通过动态