Ajax高级笔记 JavaScript高级程序设计笔记


Posted in Javascript onJune 22, 2017

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的朋友应该是个不错的入门讲解。

Javascript 相关文章推荐
javascript 自定义事件初探
Aug 21 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
Mar 18 Javascript
javascript实现控制div颜色
Jul 07 Javascript
jQuery插件实现表格隔行变色及鼠标滑过高亮显示效果代码
Feb 25 Javascript
JS原型链怎么理解
Jun 27 Javascript
JavaScript中有关一个数组中最大值和最小值及它们的下表的输出的解决办法
Jul 01 Javascript
jquery——九宫格大转盘抽奖实例
Jan 16 Javascript
vue+element-ui+ajax实现一个表格的实例
Mar 09 Javascript
浅谈vue项目打包优化策略
Sep 29 Javascript
angular4强制刷新视图的方法
Oct 09 Javascript
js实现旋转木马轮播图效果
Jan 10 Javascript
Vue.js 中制作自定义选择组件的代码附演示demo
Feb 28 Javascript
vue 请求后台数据的实例代码
Jun 22 #Javascript
深入理解vue.js中的v-if和v-show
Jun 22 #Javascript
vue如何从接口请求数据
Jun 22 #Javascript
利用node.js制作命令行工具方法教程(一)
Jun 22 #Javascript
关于在vue-cli中使用微信自动登录和分享的实例
Jun 22 #Javascript
详解vue 配合vue-resource调用接口获取数据
Jun 22 #Javascript
vue使用stompjs实现mqtt消息推送通知
Jun 22 #Javascript
You might like
用php写的serv-u的web申请账号的程序
2006/10/09 PHP
ThinkPHP通过AJAX返回JSON的两种实现方法
2014/12/18 PHP
给WordPress的编辑后台添加提示框的代码实例分享
2015/12/25 PHP
Zend Framework创建自己的动作助手详解
2016/03/05 PHP
PHP面试常用算法(推荐)
2016/07/22 PHP
Zend Framework上传文件重命名的实现方法
2016/11/25 PHP
js复制到剪切板的实例方法
2013/06/28 Javascript
Flexigrid在IE下不显示数据的有效处理方法
2014/09/04 Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
2015/12/31 Javascript
javascript中数组和字符串的方法对比
2016/07/20 Javascript
JS常见创建类的方法小结【工厂方式,构造器方式,原型方式,联合方式等】
2017/04/01 Javascript
详解vue的数据binding绑定原理
2017/04/12 Javascript
JavaScript中undefined和null的区别
2017/05/03 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
vuex2中使用mapGetters/mapActions报错的解决方法
2018/10/20 Javascript
Angular CLI 使用教程指南参考小结
2019/04/10 Javascript
layer更改皮肤的实现方法
2019/09/11 Javascript
原生js实现无缝轮播图
2020/01/11 Javascript
jQuery AJAX应用实例总结
2020/05/19 jQuery
在vue-cli3中使用axios获取本地json操作
2020/07/30 Javascript
Python处理RSS、ATOM模块FEEDPARSER介绍
2015/02/18 Python
python实现杨氏矩阵查找
2019/03/02 Python
Django admin model 汉化显示文字的实现方法
2019/08/12 Python
Django shell调试models输出的SQL语句方法
2019/08/29 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
2020/06/22 Python
python 模拟登陆163邮箱
2020/12/15 Python
python 利用panda 实现列联表(交叉表)
2021/02/06 Python
Canvas获取视频第一帧缩略图的实现
2020/11/11 HTML / CSS
个人自我鉴定怎么写
2013/10/28 职场文书
幼儿园校车司机的岗位职责
2014/01/30 职场文书
欢迎领导标语
2014/06/27 职场文书
临床医学专业求职信
2014/08/08 职场文书
关于九一八事变的演讲稿2014
2014/09/17 职场文书
群众路线调研报告范文
2014/11/03 职场文书
2014年银行个人工作总结
2014/12/05 职场文书
一年级数学上册复习计划
2015/01/17 职场文书