Ajax与Comet

一、前言

  Ajax是Asynchronous javaScript + XML的简写。这一技术能够向服务器请求额外的数据而无须卸载页面,会带来更好的用户体验。这一技术改变了自从Web诞生以来就一直沿用的'单击,等待'的交互模式。Ajax技术的核心是 XMLHttpRequest 对象(简称 XHR),在 XHR出现之前,Ajax式的通信必须借助一些 hack手段来实 现,大多数是使用隐藏的框架或内嵌框架。XHR 为向服务器发送请求和解析服务器响应提供了流畅的 接口。能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据。 也就是说,可以使用 XHR 对象取得新数据,然后再通过 DOM 将新数据插入到页面中。

二、XMLHttpRequest 对象 

  1.IE7+、Firefox、Opera、Chrome和 Safari都支持原生的 XHR对象。

    var xhr = new XMLHttpRequest();

  2.XHR用法

    xhr.open('get',url,false);//接受三个参数 请求的类型,请求的url,是否异步发送请求,open(0方法只是打开一个请求并没有真正的发送出去

    xhr.send(null);//send()方法接受一个参数,要作为请求主体发送的数据,如果没有则传入null;

  3.HTTP的头部信息

    每个http请求和响应都会带有相应的头部信息,XHR 对象也提供了操作这两种头部(即请求头部和响应头部)信息的方法。

    默认情况下,在发送 XHR 请求的同时,还会发送下列头部信息:

     Accept:浏览器能够处理的内容类型

    Accept-Charset:浏览器能够显示的字符集

      Accept-Encoding:浏览器能够处理的压缩编码

    Accept-Language:浏览器当前设置的语言

    Connection:浏览器与服务器之间连接的类型

    Cookie:当前页面设置的任何 Cookie

    Host:发出请求的页面所在的域

    Referer:发出请求的页面的 URI

    User-Agent:浏览器的用户代理字符串

  4.setRequestHeader()方法  可以设置自定义的请求头部信息,接受两个参数‘头部字段的名称’,‘头部字段的值’,setRequestHeader()只能在open()之后,send()之前调用,例:

    xhr.open("get", url, true);

    xhr.setRequestHeader("MyHeader", "MyValue");

      xhr.send(null); 

     通过getResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息

  5.get请求

   使用get请求经常会发生一个错误,就是查询字符串的格式有问题。url末尾参数的参数的名称-值必须以&连接。

   xhr.open('get','example.php?name1=value1&name2=value2',true);

   一个辅助函数向现有URL的末尾添加查询字符串参数:

    function addURLParam(url,name,value){

    url += (url.indexof("?") == -1 ? "?" : "&");

    url += endcodeURIComponent(name)+ '=' endcodeURIComponnet(value);

    return url;

   }

   const url = "example.php";

   url = add(url,"name","haha");

   xhr.open('get',url,false);

三、XMLHttpRequest 2级

  1.FormData

    FormData为序列化表单以及创建表单格式相同的数据提供了便利

    var data = new FormData();

    data.append('name','haha');

  例:

    xhr.open("post",'xxx',true);

    var form = document.getElementById("xx");

    xhr.send(new FormData(form));

四、CORS 跨域资源共享

  通过 XHR 实现 Ajax 通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR 对象只能访 问与包含它的页面位于同一个域中的资源。这种安全策略可以预防某些恶意行为。但是,实现合理的跨 域请求对开发某些浏览器应用程序也是至关重要的。

  CORS(Cross-Origin Resource Sharing,跨源资源共享)是 W3C的一个工作草案,定义了在必须访 问跨源资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的 HTTP头部 让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。 

  1、IE对CORS的实现 微软在 IE8中引入了 XDR(XDomainRequest)类型。这个对象与 XHR类似,但能实现安全可靠 的跨域通信。

    XDR与XHR的一些不同之处

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

     只能设置请求头部信息中的 Content-Type 字段。

     不能访问响应头部信息。

     只支持 GET 和 POST 请求。

    XDR的用法和XHR的用法类似,但XDR的请求都是异步的

  2、其他浏览器对CORS的实现 

    Firefox 3.5+、Safari 4+、Chrome、iOS版Safari和Android平台中的WebKit 都通过 XMLHttpRequest 对象实现了对 CORS 的原生支持。。要请求位于另一个域中的资源,使用标准的XHR对象并在 open()方法中传入绝对URL即可。

  3.CORS的基本原理

    浏览器将CORS分为“简单请求”和“非简单请求”

    满足一下两大条件就属于简单请求:

      1.请求方式是 :get、post、head之一

      2.http的头部信息不超过这些字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

    3.1基本流程

      对于简单的请求,浏览器直接发送CORS请求,浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段

      GET /cors HTTP/1.1

      Origin: http://api.bob.com

      Host: api.alice.com

      Accept-Language: en-US

      Connection: keep-alive

      User-Agent: Mozilla/5.0...

      上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包   含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

      如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段:

      Access-Control-Allow-Origin: http://api.bob.com

      Access-Control-Allow-Credentials: true

      Access-Control-Expose-Headers: FooBar

      Content-Type: text/html;

      charset=utf-8

      上面的头信息之中,有三个与CORS请求相关的字段,都以Access-Control-开头。

      (1)Access-Control-Allow-Origin     该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

      (2)Access-Control-Allow-Credentials  该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

      (3)Access-Control-Expose-Headers 该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。

      对于非简单的请求 

        非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

五、其它跨域技术

  Comet 是一种更高级的Ajax技术(也有人称为‘服务器推送’),Ajax 是一种从页面向服务器请求数据的技术,而 Comet 则是一种服务器向页面推送数据的技 术。Comet能够让信息近乎实时地被推送到页面上,非常适合处理实时数据的更新

  Comet实现的两种方式:

    长轮询和流:

      长轮询是浏览器定时向服务器发送请求。页面发起一个到服务器的请求,然后服务器一直保持连接打开,直到数据可发送。无论是短轮询还是长轮询,浏览器都要在接收数据之前,先发起对服务器的连接。两者大的区别 在于服务器如何发送数据。短轮询是服务器立即发送响应,无论数据是否有效,而长轮询是等待发送响 应。

      http流,流不同于上面两种轮询,因为他在页面的整个生命周期内只使用一个http连接。就是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周 期性地向浏览器发送数据

  web scoket:是一个在单独的持久连接上提供全双工、双向通信。在 JavaScript中创建了 Web Socket之后,会有一个 HTTP请求发送 到浏览器以发起连接。在取得服务器响应后,建立的连接会使用 HTTP 升级从 HTTP 协议交换为 Web Socket 协议。也就是说,使用标准的 HTTP 服务器无法实现 Web Sockets,只有支持这种协议的专门服 务器才能正常工作。由于 Web Sockets使用了自定义的协议,所以 URL模式也略有不同。未加密的连接不再是 http://, 而是 ws://;加密的连接也不是 https://,而是 wss://。在使用 Web Socket URL时,必须带着这个 模式,因为将来还有可能支持其他模式。

  1. Web Sockets API 

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

    WebSocket 表示当前状态的 readyState 属性:

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

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

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

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

    要关闭 Web Socket连接,可以在任何时候调用 close()方法

    socket.close(); 

  2. 发送和接收数据 

    socket.send("Hello world!"); 

    var message = {time: new Date(), text: "Hello world!", clientId: "asdfp8734rew" }; 

    socket.send(JSON.stringify(message)); //参数必须序列化

    socket.onmessage = function(event){

      var data = event.data; 

      console.log(data);

     };

    3. 其他事件 

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

    socket.onopen = function(){ //成功建立连接时的钩子函数

        alert("Connection established.");

    }; 


    socket.onerror = function(){ //发生错误时触发,连接不能持续

       alert("Connection error.");

    };

    socket.onclose = function(){ //在连接关闭时触发

       alert("Connection closed.");

    };

六、Promise

  在javaScript中,所有代码执行都是单线程执行的。所以导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行

  基本用法:

  const promise = new Promise(function(resolve, reject) {

    if (true){

     resolve(value); //把状态Promise对象状态从未完成变为成功

    } else {
      reject(error); //把状态Promise对象状态从未完成变为失败

}});
Promise.prototype.then();

  Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法

Promise.prototype.catch();
Promise.prototype.catch方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

参考文章
  <<javascript 高级程序设计>> <<ECMAScript6入门-阮一峰>><<https://www.cnblogs.com/keyi/p/6726089.html>>
  
 
 

 

posted @ 2019-04-02 16:41  蝈民党  阅读(234)  评论(0编辑  收藏  举报