- <script type="text/javascript">
- // 调用 Ajax 函数
- Ajax({
- url:'./TestXHR.aspx',
- type:'POST',
- dataType:'json',
- data:{name:"马各马它",age:18},
- success:function(response,xml){
- // 请求成功后执行的代码
- },
- error:function(status){
- // 失败后执行的代码
- }
- });
- // 创建 Ajax 函数
- function Ajax(options){
- options=options||{};
- optoins.type=(options.type||'GET').toUpperCase();
- options.dataType=options.dataType||'json';
- params=formatParams(options.data);
- // 创建 - 第一步
- var xhr;
- // 非 IE6
- if(Windows.XMLHttpRequest){
- xhr=new XMLHttpRequest();
- }else{
- //ie6 及其以下版本浏览器
- xhr=ActiveXObject('Microsoft.XMLHTTP');
- }
- // 接收 - 第三步
- xhr.onreadystatechange=function(){
- if(xhr.readyState==4){
- var status=xhr.status;
- if(status>=200&&status<300){
- options.success&&options.success(xhr.responseText,xhr.responseXML);
- }else{
- options.error&&options.error(status);
- }
- }
- }
- // 连接和发送 - 第二步
- if(options.type=='GET'){
- xhr.open('GET',options.url+'?'+params,true);
- xhr.send(null);
- }else if(options.type=='POST'){
- xhr.open('POST',options.url,true);
- // 设置表单提交时的内容类型
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- xhr.send(params);
- }
- }
- // 格式化参数
- function formatParams(data){
- var arr=[];
- for(var name in data){
- arr.push(encodeURIComponent(name)+'='+encodeURIComponent(data[name]));
- }
- arr.push(('v='Math.random()).replace('.',''));
- return arr.join('&');
- }
- </script>
如果你有看不懂的地方, 磨叽, 待我娓娓道来:
1. 创建
创建没什么好说的, 兼容各个版本的浏览器.
2. 连接和发送
2.1,open(method,url,async): 规定请求类型 (POST 或 GET), 请求地址 url, 异步(true) 同步(false). 大多都是异步;
通过 Ajax,JavaScript 无需等待服务器的响应, 而是:
在等待服务器响应时执行其他脚本
当响应就绪后对响应进行处理
2.2,GET 请求方式是通过 URL 参数将数据提交到服务器的, POST 则是通过将数据作为 send 的参数提交到服务器;
2.3,POST 请求中, 在发送数据之前, 要设置表单提交的内容类型;
2.4, 提交到服务器的参数必须经过 encodeURIComponent()方法进行编码, 实际上在参数列表 "key=value" 的形式中, key 和 value 都需要进行编码, 因为胡包含特殊字符. 每次请求的时候都会在参数列表中拼入一个 "v=xx" 的随机字符串, 这样是为了拒绝缓存, 每次都直接请求到服务器上.
encodeURI(): 用于整个 URI 的编码, 不会对本身属于 URI 的特殊字符串进行编码, 如 : / ? # 其对应的解码函数 decodeURI();
encodeURIComponent(): 用于对 URI 中的某一部分进行编码, 会对它发现的任何非标准字符进行编码; 其他对应的解码函数 decodeURIComponent();
2.5,setRequestHeader(header,value): 向请求添加请求头. header: 规定头的名称, value: 规定头的值
3. 接收
3.1, 接收到响应后, 响应的数据会自动填充 XHR 对象, 相关属性如下
responseText: 获得字符串形式的响应数据;
responseXML: 获得 xml 形式的响应数据;
status: 响应的 HTTP 状态码;
statusText:HTTP 状态的说明;
3.2,XHR 对象的 readyState 属性表示请求 / 响应过程的当前活动阶段, 这个属性的值如下
0 - 未初始化, 尚未调用 open()方法;
1 - 启动, 调用了 open()方法, 未调用 send()方法; 服务器连接已建立;
2 - 发送, 已经调用了 send()方法, 未接收到响应; 请求已接收;
3 - 接收, 已经接收到部分响应数据; 请求处理中;
4 - 完成, 已经接收到全部响应数据; 请求已完成;
只要 readyState 的值变化, 就会调用 readystatechange 事件,(其实为了逻辑上通顺, 可以把 readystatechange 放到 send 之后, 因为 send 时请求服务器, 会进行网络通信, 需要时间, 在 send 之后指定 readystatechange 事件处理程序也是可以的, 我一般都是这样用, 但为了规范和跨浏览器兼容性, 还是在 open 之前进行指定吧).
3.3, 在 readystatechange 事件中, 先判断响应是否接收完成, 然后判断服务器是否成功处理请求, xhr.status 是状态码, 状态码以 2 开头的都是成功, 304 表示从缓存中获取, 上面的代码在每次请求的时候都加入了随机数, 所以不会从缓存中取值, 故该状态不需判断.
4,Ajax 请求是不能跨域的!
二, JSONP
JSONP(JSON with Padding) 是一种跨域请求方式. 主要原理是利用了 script 标签可以跨域请求的特点, 由其 src 属性发送请求到服务器, 服务器返回 JS 代码, 网页端接受响应, 然后就直接执行了, 这和通过 script 标签引用外部文件的原理是一样的.
JSONP 由两部分组成: 回调函数和数据, 回调函数一般是由网页端控制, 作为参数发往服务器端, 服务器端把要返回的数据拼成字符串作为函数的参数传入.
比如网页端创建一个 script 标签, 并给其 src 赋值为 http://www.example.com/json/?callback=process http://www.superfiresun.com/json/?callback=process , 此时网页端就发起一个请求. 服务端将要返回的数据拼好最为函数的参数传入, 服务端返回的数据格式类似 "process({'name':'example'})", 网页端接收到了响应值, 因为请求者是 script, 所以相当于直接调用 process 方法, 并且传入了一个参数.
单看响应返回的数据, JSONP 比 Ajax 方式就多了一个回调函数.
- function JSONP(options) {
- options = options || {};
- if (!options.url || !options.callback) {
- throw new Error("参数不合法");
- }
- // 创建 script 标签并加入到页面中
- var callbackName = ('jsonp_' + Math.random()).replace(".", "");
- var oHead = document.getElementsByTagName('head')[0];
- options.data[options.callback] = callbackName;
- var params = formatParams(options.data);
- var oS = document.createElement('script');
- oHead.appendChild(oS);
- // 创建 JSONP 回调函数
- Windows[callbackName] = function (JSON) {
- oHead.removeChild(oS);
- clearTimeout(oS.timer);
- Windows[callbackName] = null;
- options.success && options.success(JSON);
- };
- // 发送请求
- oS.src = options.url + '?' + params;
- // 超时处理
- if (options.time) {
- oS.timer = setTimeout(function () {
- Windows[callbackName] = null;
- oHead.removeChild(oS);
- options.fail && options.fail({ message: "超时" });
- }, time);
- }
- };
- // 格式化参数
- function formatParams(data) {
- var arr = [];
- for (var name in data) {
- arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[i]));
- }
- return arr.join('&');
- }
1, 因为 script 标签的 src 属性只在第一次设置的时候起作用, 导致 script 标签没法重用, 所以每次完成操作之后要移除;
2,JSONP 这种请求方式中, 参数依旧需要编码;
3, 如果不设置超时, 就无法得知此次请求是成功还是失败;
来源: http://www.bubuko.com/infodetail-3091800.html