Ajax高级笔记 JavaScript高级程序设计笔记
ajax通信与数据格式无关,从服务器获取的数据不一定是xml数据。
ajax的核心:xmlhttprequest对象(简称xhr)
在xhr对象之前,ajax通信通常使用hack手段,如使用隐藏的或内嵌的框架。
xhr对象为向服务器发送信息和解析服务器响应提供了流畅的接口。
1.xmlhttprequest对象
ie5是第一款引进xhr对象的浏览器,通过msxml库中的activex对象实现(有3个版本)。
兼容所有浏览器,创建xhr对象:
function createxhr(){ if (typeof xmlhttprequest != "undefined"){ return new xmlhttprequest(); } else if (typeof activexobject != "undefined"){ if (typeof arguments.callee.activexstring != "string"){ var versions = ["msxml2.xmlhttp.6.0", "msxml2.xmlhttp.3.0", "msxml2.xmlhttp"], i, len; for (i=0,len=versions.length; i < len; i++){ try { new activexobject(versions[i]); arguments.callee.activexstring = versions[i]; break; } catch (ex){ //skip } } } return new activexobject(arguments.callee.activexstring); } else { throw new error("no xhr object available."); } }
之后就能在所有浏览器创建xhr对象:var xhr = createrxhr();
2.原生xhr对象 (支持的浏览器: ie7+、ff、chrome、opera、safari)
通过xmlhttprequest构建函数,创建xhr对象:
var xhr = new xmlhttprequest();
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”,此属性保存响应数据xml dom文档
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("request was unsuccessful:" + xhr.status); };
3-5.readystate属性
该属性存储 请求/响应过程的 当前活动状态。
0 : 未初始化,未调用open();
1 : 启动,调用了open();
2 : 发送,调用了send(),未接受响应;
3 : 接受,已接受部分响应;
4 : 完成,已接受全部响应,且可在客户端使用。
3-6.readystatechange事件
该事件,在readystate属性值改变时触发。
readystatechange事件句柄
var xhr = createxhr(); xhr.onreadystatechange = function(event){ if (xhr.readystate == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responsetext); } else { alert("request was unsuccessful: " + 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头部信息
var xhr = createxhr(); xhr.onreadystatechange = function(){ if (xhr.readystate == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responsetext); } else { alert("request was unsuccessful: " + 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查询字符串参数:
function addurlparam(url,name,value){ url += (url.indexof('?') == -1?'?':'&'); url += encodeuricomponent(name) + '=' + encodeuricomponent(value); return url; }
6、post请求
长用于想服务器发送要保存的数据。
由于xhr其初的设计是为了处理xml,故在send(0中可传入xhr dom文档。
6-1.服务端读取post数据
①默认情况下,服务器对post请求和提交web表单不会一视同仁,故服务端需要程序来读取发送的原始数据,并解析出有用部分。
②xhr模拟表单提交:
1.将content-type头部信息设置为application/x-www-form-urlencoded (即表单提交时的内容问题);
2.以适当格式创建一个字符串。(通过serialize()函数创建该字符串,序列化表单数据)
xhr模拟表单提交
function submitdata(){ var xhr = createxhr(); xhr.onreadystatechange = function(event){ if (xhr.readystate == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responsetext); } else { alert("request was unsuccessful: " + xhr.status); } } }; xhr.open("post", "postexample.php", true); xhr.setrequestheader("content-type", "application/x-www-form-urlencoded"); var form = 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事件
var xdr = new xdomainrequest(); 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的跨域
var xhr = createxhr(); xhr.onreadystatechange = function(){ if (xhr.readystate == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responsetext); } else { alert("request was unsuccessful: " + 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跨域兼容
function createcorsrequest(method, url){ var xhr = new xmlhttprequest(); if ("withcredentials" in xhr){ xhr.open(method, url, true); } else if (typeof xdomainrequest != "undefined"){ xhr = new xdomainrequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } var request = createcorsrequest("get", "http://www.somewhere-else.com/xdr.php"); if (request){ request.onload = function(){ //do something with request.responsetext }; request.send(); }
上述createcorsrequest()函数返回的对象的属性(xhr和xdr的共同属性):
①abort():停止正在进行的请求;
②onerror:用于替代onreadystatechange检测错误;
③onload:用于代替onreadystatechange检测成功;
④responsetext:用于取得响应内容;
⑤send():用于发送请求。
8、其他跨域技术
在cors出现前,常利用dom中能够执行跨域请求的功能,在不依赖xhr对象时,也能发送某种请求。
与cosr不同的是,不用修改服务器代码。
8-1.图像ping
使用<img>标签,由于可以从任何网页加载图像,故常是在线广告跟踪浏览量的只要方式。
可动态创建图像,使用它们的onload和onerror事件句柄,确定是否接受到了响应。
var img = new image(); 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(json width padding)填充式json或参数式json,类似json,是包含在函数调用中的json:
callback( {"name" : "value"} );
8-2-1.jsonp有两个部分:回调函数 和 数据
回调函数:当响应到来时应该在页面中调用的函数。回调函数的名称在请求中指定。
数据:传入回调函数的json数据。
8-2-2.jsonp通过动态<script>元素,为其src属性指定一个跨域的url。类似<img>元素,即都能不受限制地跨域加载资源。
jsonp为有效的javascript代码,在请求完成即jsonp响应 加载到页面后就会立即执行。
function handleresponse(response){ alert("you're at ip address " + response.ip + ", which is in " + response.city + ", " + response.region_name); } var script = document.createelement("script"); script.src = "http://freegeoip.net/json/?callback=handleresponse"; document.body.insertbefore(script, document.body.firstchild);
headleresponse()为回调函数,将在响应到来后执行。
8-2-3.jsonp之所以流行,是因为 :
①能够直接访问响应文本;
②支持浏览器与服务器之间的双向通信。
不足:
①jsonp从其他域加载代码执行,因此该域必须安全可靠;
②很难确保jsonp请求是否失败。
8-3comet ”服务器推送" 【不兼容ie】
ajax从页面想服务器请求数据,comet则是服务器向页面推送数据,comet能近乎实时地向页面推送信息。
8-3-1.实现comet的2种方式:长轮询 和 流
①长轮询:与短轮询相反,页面发送一个请求,服务器一直保持连接打开,直到有数据可发送时就向页面发送数据。接收完数据后浏览器关闭连接,随机又发送一个新请求,在页面打开期间如此循环...
【短轮询是服务器立即发送数据,即使数据无效,长轮询是等待发送响应。】
轮询的优点是,所有浏览器都支持。通过xhr对象和settimeout()实现。
②http流:它在网页的整个生命周期内只使用一个http连接。浏览器发送一个请求,服务器保持连接打开,再周期性向浏览器发送数据.
php例子
<?php $i = 0; while (true) { //输出一些数据,然后刷新输出缓存 echo "number is $1"; flush(); //等几秒 sleep(10); $++; } ...
实现http流的关键:所有服务器端语言都支持打印到输出缓存然后刷新的功能。(将输出缓存中的内容一次性全部发送给客户端)
使用xhr实现http流的典型例子
var xhr = new xmlhttprequest(), received = 0; xhr.open("get", url, true); xhr.onreadystatechange = function(){ var result; if (xhr.readystate == 3){ //get only the new data and adjust counter result = xhr.responsetext.substring(received); received += result.length; //call the progress callback progress(result); } else if (xhr.readystate == 4){ finished(xhr.responsetext); } }; xhr.send(null); return xhr; } var client = createstreamingclient("streaming.php", function(data){ alert("received: " + data); }, function(data){ alert("done!"); });
以上就是小编为大家分享的ajax高级笔记的相关内容,对于学习ajax的朋友应该是个不错的入门讲解。
下一篇: Linux系统编程-基础概念篇