JS红宝书读书笔记 — 21.Ajax与Comet

21.Ajax与Comet

21.1.XMLHttpRequest对象
  • 创建

    var xhr = new XMLHttpRequest();
    // IE7+, Firefox等等
    
21.1.1.XHR的用法
  • open():启动一个请求以备发送

    // 接受三个参数:请求类型,请求URL(相对于执行代码的当前页面或绝对路径),是否异步发送请求
    xhr.open("get", "example.php", false); 
    
  • send():发送请求

  • abort():取消异步请求

  • 收到响应

    • 响应的数据会自动填充XHR对象的属性

      • responseText:作为响应主体被返回的文本
      • responseXML:如果响应的内容类型是"text/xml"或者"application/xml",这个属性将保存包含响应数据的XML DOM文档,对非XML数据而言,responseXML属性将为null
      • status:响应的HTTP状态
      • statusText:HTTP状态说明
    • 检测 status 属性并操作

      if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
        alert(xhr.responseText);
      } else {
        alert("Request was unsuccessful: " + xhr.status);
      }
      
  • XHR对象的 readyState 属性表示请求/响应过程的当前活动阶段

    • 0:未初始化。尚未调用open()方法

    • 1:启动。已经调用open()方法,但尚未调用send()方法

    • 2:发送。已经调用send()方法,但尚未接收到响应

    • 3:接受。已经接收到部分响应数据

    • 4:完成。已经接收到全部响应数据,并且已经可以在客户端使用了

      var xhr = new XMLHttpRequest(); // 0
      xhr.open('get', 'http://localhost:3000/readystate'); // 1
      xhr.onreadystatechange = function() { // 2, 3, 4
          alert(xhr.readyState);
        	if(xhr.readyState == 4) {
            	console.log(xhr.responseText);
          }
      };
      xhr.send();
      
21.1.2.HTTP头部信息
  • 设置属性

    • Accept:浏览器能够处理的内容类型
    • Accepy-Charset:浏览器能够显示的字符集
    • Accept-Encoding:浏览器能够处理的压缩编码
    • Accept-Language:浏览器当设置的语言
    • Connection:浏览器与服务器之间连接的类型
    • Cookie:当前页面设置的任何Cookie
    • Host:发送请求的页面所在的域
    • Referer:发送请求的页面的URI
  • 用法

    // 在调用 open() 方法之后且调用 send() 方法之前调用 setRequestHeader()
    xhr.open("get", "example.php", true);
    xhr.setRequestHeader("MyHeader", "MyValue");  // key && value
    xhr.send(null);
    
  • 获取属性

    var myHeader = xhr.getResponseHeader("MyHeader");
    var allHeaders = xhr.getAllResponseHeaders();
    
21.1.3.GET请求
  • 查询字符串中的每个拿书的名称和值必须使用encodeURIComponent() 进行编码

  • 所有的键值对都必须以和号 & 分隔

    xhr.open("get", "example.php?name1=value1&name2=value2", true);
    
    function addURIParam(url, name, value) {
    	url += (url.indexOf("?") == -1 ? "?" : "&");
    	url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
      return url;
    }
    
21.1.4.POST请求
  • 使用XHR模仿表单提交

    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));
    
  • 发送相同的数据,GET请求的速度最多可达POST请求的两倍

21.2.XMLHttpRequest 2级
21.2.1.FormData
var data = new FormData();
data.append("name", "ming");

xhr.open("post", "postexample.php", true);
var form = document.getElementById("user-info");
xhr.send(new FormData(form));
  • 使用FormData的方便之处体现在不必明确地在XHR对象上设置请求头部。XHR对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息
21.2.2.超时设定
21.2.3.overideMimeType()方法
  • 用于重写XHR响应的MIME类型
var xhr = creatXHR();
xhr.open("get", "text.php", true);
xhr.overrideMimeType("text/xml");
xhr.send(null);
21.3.进度事件
  • loadstart:在接收到响应数据的第一个字节时触发
  • progress:在接收到响应期间持续不断地触发
  • error:在请求发生错误时触发
  • abort:在因为调用abort( )方法而终止连接时触发
  • load:在接受到完整的响应数据时触发
  • loadend:在通信完成或触发error、abort或load事件后触发
21.3.1.load事件
var xhr = createXHR();
xhr.onload = function() {
  if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  	alert(xhr.responseText);
	} else {
  	alert("Request was unsuccessful: " + xhr.status);
	}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
  • 只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件
21.3.2.progress事件*
21.4.跨域资源共享
  • 来源于跨域安全策略,默认情况下XHR对象只能访问域包含它的页面位于同一个域中的资源,这种安全策略可以预防某些恶意行为

  • CORS( Cross-Origin Resource Sharing,跨域资源共享 )

    • 使用自定义的HTTP头部让浏览器与服务器进行沟通

    • 发送请求时,需要额外附加Origin头部,其中包含请求页面的源信息( 协议、域名和端口 ),以便服务器根据这个头部信息来决定是否需要给予响应

      //example
      Origin: http://www.nczonline.net
      
    • 如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin 头部回发相同的源信息,如果是公共资源,可以回发*

      Access-Control-Allow-Origin: http://www.nczonline.net
      
    • 请求和响应都不包含cookie信息

21.4.1.IE对CORS的实现
  • IE8引入了XDR类型,缓解了CSRF和XSS
21.4.2.其他浏览器对CORS的实现
  • 通过XMLHttpRequest对象实现了对CORS的原生支持
21.4.3.Preflighted Requests
  • CORS通过一种叫做Preflighted Requests的透明服务器验证机制支持开发人员使用自定义的头部、GET或POST之外的方法,以及不同类型的主题内容

  • 使用方法

    • 客户端

      Origin: http://www.nczonline.net
      Access-Control-Request-Method: POST     // 逗号隔开
      Access-Control-Request-Headers: NCZ
      
    • 服务端

      Access-Control-Allow-Origin:  http://www.nczonline.net
      Access-Control-Allow-Origin: POST, GET
      Access-Control-Allow-Origin: NCZ
      Access-Control-Max-Age: 1728000
      
  • Preflight请求结束后,结果将按照响应中指定的时间啊缓存起来,而为此付出的代价只是多发送一次HTTP请求

21.4.4.带凭据的请求
  • 默认情况下跨域请求不提供凭据( cookie,HTTP认证及客户端SSL证明等 )

  • 通过将 withCredentials 属性设置为true,可以指定某个请求应该发送凭据

  • 如果服务器接受带凭据的请求,会用下面的HTTP头部来响应

    Access-Control-Allow-Credentials: true
    
  • 如果发送的是带凭据的请求,但服务器的响应中没有包含这个头部,那么浏览器就不会把响应交给JS

21.4.5.跨浏览器的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;
  }
}
var request = createRequest("get", "http://www.somewhere-else.com/page/");
if(request){
  request.onload = function() {
    // 对response进行处理
  };
  request.send();
}
21.5.其他跨域技术
21.5.1.图像Ping
  • 一个网页可以从任何网页中加载图像,不用担心跨不跨域

  • 是在线广告跟踪浏览量的主要方式

  • 请求通常是以查询字符串的形式发送的,而响应可以是任意内容

  • 通过图像Ping,浏览器得不到任何具体的数据,但通过侦听load和error事件,它能知道响应是什么时候接收到的

  • 实现

    var img = new Image();
    img.onload = img.onerror = function() {
    	alert("Done");
    };
    img.src = "http://www.example.com/test?name=ming"
    
  • 缺点

    • 只能发送GET请求
    • 无法访问服务器的响应文本,只能用于浏览器与服务器间的单向通信
21.5.2.JSONP
  • JSONP由两部分组成:回调函数和数据

    • 回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的
    • 数据就是传入回调函数中的JSON数据
  • 原理

    • JSONP通过动态

21.5.3.Comet#
  • 实现方式
    • 长轮询
21.5.4.服务端发送事件*
21.5.5.Web Sockets*
21.5.6.SSE与Web Socket2*
21.6.安全
  • CSRF( Cross-Site Request Forgery ) 跨站请求伪造
    • 未被授权的系统会伪造自己,让处理请求的服务器认为它是合法的
    • 解决方法:验证发送者是否有权限访问相应的资源
      • 要求以SSL连接来访问可以通过XHR请求的资源
      • 要求每一次请求都要附带经过相应算法计算得到的验证码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值