javascript学习笔记——Ajax、跨资源共享(CORS)、图像Ping、JSONP、Comet、Web Socket

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_39067385/article/details/81566533

Ajax(Asynchronous JavaScript+XML)

虽然Ajax名字包含XML成分,但是Ajax通信与数据格式无关;从服务器取得的数据不一定是XML数据;

Ajax技术能够向服务器请求额外的数据为无须卸载页面

核心是:XMLHttpRequest对象(XHR),XHR为向服务器发送请求和解析服务器相应提供了流畅的接口

1.XHR的用法

var xhr=new XMLHttpRequest);
xhr.onreadystatechange=function(){
   if(xhr.readyState==4){
      if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
          alert(xhr.responseText);
         //取得相应的的响应头部信息
         xhr.getResponseHeader("MyHeader");
         //取得所有的头部信息
         xhr.getAllResponseHeaders();
      }else{
          alert("request is unsuessful"+xhr.status);
      }
   }
};
//false表示同步请求
xhr.open("get","example.php",true);      
//自定义HTTP头部信息
xhr.setRequestHeader("MyHeader","MyValue"); 
xhr.timeout=1000;    //设置超时时间为1秒钟
xhr.ontimeout=function(){
  alert("request did not return in a second");
}
//不需要通过请求主体发送数据,则必须传入与null;
xhr.send(null);

这段代码会启动针对example.php的GET请求。

注意:

① open方法中第二个参数URL是相对于执行代码的当前页面;

调用open()方法并不会真正地发送请求,只是准备一个请求以备发送

③ 调用send()之后,请求就会被分派到服务器;

只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件

⑤ 必须在调用open()之前指定onreadystatechange事件处理程序才能确保浏览器的兼容性;

⑥ 调用abort()方法可以取消异步请求,XHR对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性;

 2.HTTP头部信息

setRequestHeader(头部字段名称,头部字段的值)方法可以设置自定义的请求头部信息

必须在调用open方法之后,且调用send方法之前;

 GET请求

最常见的请求类型,常常用于向服务器查询某些信息;

可以将查询字符串的参数追加到URL末尾,以便将信息发送到服务器。

open方法的URL末尾的查询字符串必须经过正确的编码才行。

下面的函数可以辅助向现有的URL的末尾添加查询字符串参数

function addURLParam(url,name,value){
    url+=(url.indexOf("?")==-1?"?":"&");
    url+=encodeURIComponent(name)+"="+encodeURIComponent(value);
    return url;
}

 post请求

通常用于向服务器发送应该被保存的数据。

post请求的主体可以包含非常多的数据,而且格式不限; 

 FormData类型

用于序列化表单;创建与表单格式相同的数据;

优点:不必明确地在XHR对象上设置请求头部,XHR对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息;

var data=new FormData();
data.append("name","coco");
var xhr=new XMLHttpRequest);
xhr.onreadystatechange=function(){
   if(xhr.readyState==4){
      if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
          alert(xhr.responseText);
      }else{
          alert("request is unsuessful"+xhr.status);
      }
   }
};
//false表示同步请求
xhr.open("post","example.php",true);      
//不需要通过请求主体发送数据,则必须传入与null;
xhr.send(data);

overrideMimeType()方法用于重写xhr响应的MIME类型;

xhr.overrideMimeType("text/xml");

强迫XHR对象将响应当做XML而非纯文本来处理。

调用该方法必须在send()方法之前,才能保证重写响应的MIME类型;

 3.进度事件

 loadstart:在接收到响应数据的第一个字节触发;

progress:在接收到响应期间持续不断地触发;(可以为用户创建一个进度指示器

  1)lengthComputable:一个表示进度信息是否可用的布尔值;

  2)position:表示已经接收的字节数;

  3)totalSize:表示根据Content-Length响应头部确定的预期字节数;

error:在请求发生错误时触发;

abort:在因为调用abort()方法而终止连接时触发;

load:在接收到完整的响应数据时触发。(IE8+只支持load事件)

loadend:在通信完毕或者触发error、abort、或load事件后触发;

 load事件代替readystatechange事件。响应接收完毕就触发load事件,因此不必检查readyState属性

var xhr=new XMLHttpRequest);
xhr.onload=function(){
      if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
          alert(xhr.responseText);
         //取得相应的的响应头部信息
         xhr.getResponseHeader("MyHeader");
         //取得所有的头部信息
         xhr.getAllResponseHeaders();
      }else{
          alert("request is unsuessful"+xhr.status);
      }
};
xhr.progress=function(event){
   var divStatus=document.getElementById("sattus");
   if(event.lengthComputable){      //进度信息是否可用
      divStatus.innerHTML="received"+event.position+"of"+event.totalSize+"bytes";
   }
};
//false表示同步请求
xhr.open("get","example.php",true);      
//不需要通过请求主体发送数据,则必须传入与null;
xhr.send(null);

必须在调用open方法之前添加onprogress事件处理程序;

 跨资源共享(CORS)

默认情况下,XHR对象只能访问与包含它的页面位于同一域中的资源。这种安全策略可以预防某些恶意行为。

CORS定义了在必须访问跨源资源时,浏览器与服务器之间应该如何沟通。

基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败;

 IE对CORS的实现

IE引入了与XHR类似的XDR类型实现安全可靠的跨域通信

XDR与XHR的不同之处:

①cookie不会随请求发送,也不会随响应返回;

②只能设置请求头部信息中的content-type字段;

③不能访问响应头部信息;

④只支持GET和POST请求;

所有的XDR请求都是异步执行的,不能用它来创建同步请求

因此,open方法只接受两个参数,请求类型和URL;

接收到响应后,只能访问相应原始文本,没有办法确定响应的状态码

只要有响应就会触发load事件,如果失败(响应中缺少Access-Control-Allow-Origin头部)就会触发error事件;

建议不要忘记通过onerror事件处理程序来捕获,否则,即使请求失败也不会有任何提示。

var xdr =new XDomainRequest();
xdr.onload=function(){
    alert(xdr.responseText);
};
xdr.onerror=function(){
  alert("error");
};
xdr.timeout=1000;
xdr.ontimeout=function(){
   alert("request took too long");
};
xdr.open("get","http://www.somewhere.com/page/");
xdr.send(null);

 其他浏览器对CORS的实现

要请求位于另一域中的资源,使用标准的XHR对象并在open方法中传入绝对URL即可;

与IE中的XDR对象的区别:

①跨域XHR对象可以访问status和statusText属性;

②支持同步请求

限制:(为了安全)

①不能使用setRequestHeader()设置自定义头部;

②不能发送和接收cookie;

③调用getAllResponseHeaders()方法总会返回空字符;

无论同源请求还是跨源请求都使用相同的接口,因此对于本地资源最好使用相对URL,在访问远程资源时再使用绝对URL

var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
   if(readyState==4){
      if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
         alert(xhr.responText);
    }else{
       alert("request"+xhr.status); 
    }
  }
};
xhr.open("get","http://www.somwhere.com/page/",true);
xhr.send(null);

 图像Ping

图像Ping是与服务器进行简单、单向的跨域通信的一种方式。

最常用于跟踪用户点击页面动态广告曝光次数

缺点:只能发送GET请求;无法访问服务器的响应文本。

动态创建图像经常用于图像Ping;

请求的数据是通过查询字符串的形式送的,而响应可以是任意内容,但通常是像素图或204响应。

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

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

JSONP

JSONP(JSON with padding),又叫填充式JSON或参数式JSON,应用JSON的一种新方法。(被包含在回调函数中的JSON

组成:回调函数、数据

回调函数:是当响应到来时应该在页面中调用的函数。回调函数的名字一般在请求中指定

数据:就是传入回调函数中的JSON数据

JSONP是通过动态<script>元素来使用的,使用时可以为src属性指定一个跨域的URL。<script>和<img>一样都有能力不受限制地从其他域中加载资源。

优点:

简单易用,能够直接访问响应文本,支持在浏览器和服务器之间的双向通信

缺点:

① 容易从其他域中的响应夹带一些恶意代码,如果不是自己运维的WEB服务器,那么一定要保证安全可靠;

② 不容易确定JSONP的请求成功与否。因为目前没有浏览器支持HTML5中<script>元素新增的onerror事件处理程序;

//通过查询地理定位服务来显示你的IP和位置
function handleResponse(response){
   alert("ip:"+response.ip+"city:"+response.city+"name:"+response.region_name);
}
var script=document.createElement("script");
script.src="http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script,document.body.firstchild);

Comet

Comet指的是更高级的Ajax技术(服务器推送),是一种服务器向页面推送数据的技术,信息能够近乎实时地被推送到页面上,适合用于处理体育比赛的分数股票报价

实现Comet的两种方式:

长轮询和流

长轮询是短轮询的一个翻版;

轮询是所有的浏览器都支持的;

无论长轮询还是短轮询,浏览器都要在接收数据之前,先发起对服务器的连接;

使用XHR对象和setTimeout()就能实现,主要是要考虑什么时候发送请求;

HTTP流

在页面的整个生命周期内只使用一个HTTP连接。即,浏览器发送一个请求,而服务器保持连接打开,然后周期性的向浏览器发送数据;(只有部分浏览器原生支持

实现:

通过侦听readystatechange事件及检测readyState的值是否为3,就可以利用XHR对象实现HTTP流。

随着不断从服务器接收数据,readyState的值会周期性地变为3。当readyState值变为3时,responseText属性就会保存所有的数据。此时,比较此前接收到的数据,决定从什么位置开始取得最新的数据

function createStreamingClient(url,progress,finished){
    var xhr=new XMLHttpRequest(),received=0;
    xhr.open("get",url,true);
    xhr.onreadystatechange=function(){
       var result;
       if(xhr.readyState==3){
         //取得最新数据并调整计数器
         result=xhr.responseText.substring(received);
         received+=result.length;
        //调用progress回调函数
        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")});

 Comet接口

1)SSE (Server-Sent Events,服务器发送事件)

SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据

服务器响应的MIME类型必须是text/event-stream;

SSE支持短轮询、长轮询和HTTP流,而且能在断开连接时自动确定何时重新连接

 2)Web Sockets

目标:在一个单独的持久连接上提供全双工,双向通信

创建Web Socket=》连接=》取得响应=》转换协议

使用标准的HTTP服务器无法实现Web Sockets,只有支持这种协议的服务器才能正常工作;

Web Sockets使用的是自定义协议

自定义协议的好处:

客户端和服务器之间发送的数据非常少量,非常适用于移动端;

缺点:

存在一致性和安全性的问题

① 创建对象:

var socket=new WebSocket("ws://www.example.com/server.php");

必须给WebSocket构造函数传入绝对URL。同源策略对WebSocket不适用,因此可以通过它来打开到任何站点的连接。至于是否会与某个域的页面通信,则完全取决于服务器。

② readyState属性(永远从0开始

实例化了WebSocket对象后,浏览器就马上尝试创建连接;

属性值:

WebSocket.OPENING(0):正在建立连接;

WebSocket.OPEN(1):已经建立连接;

WebSocket.CLOSING(2):正在关闭连接;

WebSocket.CLOSE(3):已经关闭连接;

WebSocket没有readystatechange事件

③ 关闭连接;

socket.close()   调用之后readyState的值立即变为2,关闭连接后就会变成3。

close事件的event对象有额外的三个属性:

     wasClean:布尔值,表示连接是否已经明确地关闭;

     code:服务器返回的数值状态;

    reason:是一个字符串,包含服务器发回的消息;

var socket=new WebSocket("ws://www.example.com/server.php");
//成功建立连接时
socket.onpen=(){
alert("opened");
};
//发送简单数据
socket.send("hello world");
//复杂数据
var message={
 time:new Date(),
 text:"hello world",
 clientId:"23werew"
};
socket.send(JSON.stringify(message));
//接收数据
socket.onmessage=function(event){
  var date=event.data;
  alert(date);
};
//发生错误
socket.onerror=function(){
  alert("connection error");
};
//关闭连接
socket.onclose=function(event){
 console.log("was clean?"+event.wasClean+" Code="+event.code+" reason="+event.reason);
};

 使用SSE还是Web Sockets的考虑因素:

① 是否有自由度建立和维护Web Socket服务?因为Web Socket协议不同于HTTP,所有现有的服务器不能用于Web Socket通信;

② 到底需不需要双向通信。SSE =>单向    Web Socket=>双向

如果只需要读取服务器数据,那么选择SSE比较简单实现;

 确保XHR访问URL安全的做法:

①  要求以SSL连接来访问可以通过XHR请求的资源;

②  要求每一次请求都要附带经过相应算法计算得到的验证码;

 CSRF:未被授权系统有权访问某个资源的情况

对防范CSRF不起作用的措施有:

① 要求发送POST而不是GET请求;

②检查来源URL以确定是否可信;

③基于cookie信息进行验证;

猜你喜欢

转载自blog.csdn.net/baidu_39067385/article/details/81566533