基石-初见浏览器(二):AJAX和跨域

AJAX技术

AJAX是对 Asynchronous JavaScript + XML 的简写。这一技术能够向服务器请求额外的数据而无须卸载页面,会带来更好的用户体验。
AJAX的核心是XMLHttpRequest 对象(简称 XHR),这是由微软首先引入的一个特性,其他浏览器提供商后来都提供了相同的实现。

XHR对象

XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据。

创建XHR对象

支持IE7及以上的兼容写法

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){ //跳过 } }
        }   
    return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("18772332810 XHR object available."); 
        }
}

使用XHR对象

  • open()方法
  • 在使用 XHR 对象时,要调用的第一个方法是open(),它接受3个参数:要发送的请求的类型( “get”、”post”等)、请求的 URL 和表示是否异步发送请求的布尔值
  • 调用open()方法不会发送网络请求,只是启动一个请求以备发送。
  • send()方法
    • 接受一个参数,作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null。(这个参数对于有些浏览器来说是必须的)
    • 调用send()之后,请求就会派发到服务器,当收到相应后,相应的数据会自动填充XHR对象的属性。
  • XHR对象的属性
    • responseText:
      响应主体被返回的文本
    • responseXML:
      如果响应的内容类型是”text/xml”或”application/xml”,这个属性中将保 存包含着响应数据的 XML DOM 文档
    • status:
      响应的 HTTP 状态
    • statusText:
      HTTP 状态的说明

接收到响应后,检查status属性,以确保响应已成功返回。为了更可靠的跨浏览器,应使用status属性来判断是否成功响应。

  • readyState属性

    • 检测XHR对象的readyState属性,该属性表示请求/响应过程中的当前活动阶段。
      0: 还未调用open()
      1: 还未调用send()
      2: 调用send()但是服务器没有响应
      3: 服务器接收响应,已经接收到一部分响应数据
      4: 已经全部响应数据,可以在客户端使用

    • 只要 readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件,通常,我们只对 readyState 值为 4 的阶 段感兴趣,因为这时所有数据都已经就绪。

    var xhr = cerateXHR();
    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.txt",true);
    xhr.send(null);
    
  • abort()方法
    调用这个方法后,XHR 对象会停止触发事件,也不再允许访问任何与响应有关的对象属性。

HTTP头部信息

  • 每个HTTP请求和响应都会带有相应的头部信息,XHR可以操作这两种头部信息。

  • 默认情况下将发送一下头部信息

    )

  • setRequestHeader()
    可以设置自定义的请求头部信息,这个方法接受两个参数:头部字段 的名称和头部字段的值。要成功发送请求头部信息,必须在调用 open()方法之后且调用 send()方法 之前调用 setRequestHeader()。

  • getResponseHeader()
    传入头部字段名称,可以取得相应的响应头部信息。

  • getAllResponseHeaders()
    取得一个包含所有头部信息的长字符串。

  • 建议使用HTTP请求头时候不要发送浏览器默认字段,否则会影响服务器的响应(要前后端字段统一化)

GET请求

  • GET是最常见的请求类型,最常用于向服务器查询某些信息,必要时,可以将查询字符串参数追加到 URL 的末尾,以便将信息发送给服务器。对 XHR 而言,位于传入 open()方法的 URL 末尾的查询字符串必须经过正确的编码才行。

  • 查询字符串中每个参数的名 称和值都必须使用 encodeURIComponent()进行编码,然后才能放到 URL 的末尾;而且所有名-值对 儿都必须由和号(&)分隔

    xhr.open("get", "example.php?name1=value1&name2=value2", true)
    
  • 辅助向现有URL的末尾添加查询字符串参数

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

POST请求

  • 通常用于向服务器发送应该被保存的数据,使用send()向服务发送数据。
  • 与 GET 请求相比,POST请求消耗的资源会更多一些。从性能角度来看,以发送相同的数据计,GET 请求的速度最多可达到 POST 请求的两倍。

XMLHttpRequest2级

XMLHttpRequest1级只是把已有的 XHR 对象的实现细节描述了出来。而 XMLHttpRequest2级则进一步 发展了 XHR,由W3C组织着手制定。

FormData

  • 表单数据的序列化的频繁使用,XMLHttpRequest 2 级为此定义了 FormData 类型。
  • 使用 FormData 的方便之处体现在不必明确地在 XHR 对象上设置请求头部。XHR对象能够识别传入的数据类型是 FormData 的实例,并配置适当的头部信息。

超时设定

XHR对象添加了一个 timeout 属性,表示请求在等待响应多少毫秒之后就终止。 在给 timeout 设置一个数值后,如果在规定的时间内浏览器还没有接收到响应,那么就会触发 timeout 事件,进而会调用 ontimeout 事件处理程序。

进度事件

Load事件

有了load事件就没必要再去监控readyState属性。只要浏览器接收到服务器的响应,不管其状态如何,都会触发 load 事件。而这意味着你必须要检 查 status 属性,才能确定数据是否真的已经可用

var xhr = createXHR();
xhr.onload = function () {
  if( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
    alert(xhr.responseText);
  }else{
    alert("was unsuccessful :" + xhr.status);
  }
};
xhr.open("get","example.php",true);
xhr.send(null);

封装AJAX函数

function ajax(method, url, data, cb) {
    // 存储一次请求中所有的信息  包括请求信息  和 响应的信息
    var xhr = null;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
      // 监听响应
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                cb(JSON.parse(xhr.responseText))
            } else {
                console.log('error');
            }
        }
    }
    if (method == 'GET') {
        // 建立连接
        xhr.open(method, url + '?' + data, true);
        // 发送信息
        xhr.send();
    } else {
        xhr.open(method, url, true);
        // 在数据传递的过程中 编码格式为key=value&key1=val1
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        // 发送信息
        xhr.send(data);
    }
}

以及JQuery的AJAX函数

      $.ajax({
        // 请求方式
        type: "GET",
        // 请求地址
        url: "http://localhost:3000/data",
        // 请求数据 (参数)
        data: {
          page: 1
          // appkey: 'DuYimeiqi_1564986205860'
        },
        // 发出请求之前执行的函数  请求前的拦截
        beforeSend: function(xhr, request) {
          console.log(request);
          request.url += "&size=1";
        },
        // 响应的拦截
        dataFilter: function(data, type) {
          console.log(data, type);
          return ;
        },
        // 编码类型 指的是 前端传递到接口的过程当中数据格式
        // contentType: '',
        // 你希望得到的数据类型  json代表的是json对象的格式
        dataType: "json",
        // 成功的回调函数
        success: function(res) {
          console.log(res);
        },
        // 错误的回调函数
        error: function(err, msg) {
          console.log(err, msg);
        }
      });

跨域

跨域可以分为两类跨域,一类是客户端与服务器之间的跨域,另外一类是客户端和客户端之间的跨域。先简单整理下客户端和服务器之间的跨域方案。

跨域源资源共享(CORS)

通过XHR对象实现AJAX通信的一个主要限制来源于浏览器的同源安全策略。同源策略规定XHR对象只能够访问与包含他的页面位于同一个域中的资源。这种安全策略可以预防某些恶意行为。但是实现合理的跨域请求对于实际开发也是非常重要的。

通过CORS跨域需要浏览器和服务器同时支持,在IE8、9使用CORS需要通过XDR对象来实现。

只要后端实现了CORS,浏览器会自动进行CORS通信。在服务器端设置Access-Control-Allow-Origin就可以开启CORS,该属性表示来自哪里的域名可以访问服务器上的资源,如果设置通配符,表示所有网站都可以访问资源。

通过CORS这种方式解决跨域问题,会在发送请求时出现两种情况,分别是简单请求和非简单请求。

简单请求

只能使用以下方法进行发送请求,同时不能够设置请求头信息和cookie等凭证信息。

  1. 请求方法:GET POST HEAD
  2. 请求头信息:无自定义请求头,同时Content-Type只支持如下字段
    • Applaction-x-www-form-urlencoded
    • Text/plain
    • Multipart/form-data

非简单请求

预检请求

主要有两种非简单请求,分别是预见请求,能够自定义请求头以及不同类型的主体内容;同时能够使用简单请求以外的方法进行发送网络请求。

带凭证的请求

默认情况下,跨域请求不携带(cookie、HTTP认证以及客户端SSL证明等),通过设置withCredentials属性值为true,可以指定某个请求应该发送凭证

图像Ping跨域

图像ping跨域技术是与服务器进行简单的、单向的跨域一种方式。

var img = new Image();
img.onload = img.onerror = function () {
	alert("Done")!;
};
img.src = "http:..."

将onload和onerror事件处理程序指定同一函数,无论是什么相应,只要请求完成就会收到通知。

通常用于跟踪用于点击页面或者动态广告曝光次数。但是也有两个主要缺点:

  1. 无法接受服务的响应
  2. 只能发送GET请求

JSONP跨域

JSONP是JSON with padding的简写,是应用JSON的一种新方法,在现代Web服务中非常流行。

JSONP由两个部分组成:

  • 回调函数

    function Response(response){
    	alert(response.name);
    }
    var script = doucment.createElement("script");
    script.src = "http://...";
    document.body.insertBefore(script,document.body.firstChild);
    
  • 数据

callback({
	"name" : "Supy"
})

同时修改URL网络请求,指定回调函数的名字为Response。

http://.../?callback = Response

JSONP优点是能够访问服务器响应信息,支持在浏览器与服务器之间的双向通信。同时他的缺点有两点:

  1. 无法确保请求网站的安全性
  2. 无法确定JSONP请求是否失败

Web Sockets

客户端与客户端进行跨域

未完待续…

https://juejin.im/post/5dfca4826fb9a0163d1a6aad

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论