ajax

1、ajax

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。能够无刷新页面而局部改变页面内容。

ajax的核心是 XMLHttpRequst 对象(简称 XHR)。

 2、XMLHttpRequest 对象

IE 5 是第一个引入 XHR 的浏览器,在 早期的 IE 中 XHR 是通过 MSXML库中的一个ActiveX对象实现的。

在 IE 中可能会遇到三个不同版本的XHR 对象:"MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"。

在 IE7+ 、Firefox、Opera、Chrome、Safari中都支持原生的XHR对象

function createXHR(){
    if(typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest();
    }else if(typeof ActiveXObject !="undefined"){ // 兼容ie 7-
        if(typeof arguments.callee.activeXString != "string"){
            var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
            var i,len;
            for(i=0,len=versions.length;i<len;i++){
                try{
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                }catch (e) {
                    //跳过
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
        
    }else{
        throw new Error("No XHR object available.");
    }
}

 3、XHR 的用法

1)xhr.open(method, url, isAsynchronous),参数:请求的方法("post","get"),请求的url,是否是异步请求(true,false,一个可选的布尔参数,默认为true,如果multipart属性为true则这个必须为true,否则将引发异常。

open()方法是启动一个请求,但并不会发送请求。

2)xhr.send(data):用于发送 HTTP 请求。如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。

               参数是 作为请求体的数据,如果没有需要通过请求体发送的数据,则为null

void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);

收到响应后,响应的数据会自动填充XHR对象的属性:

xhr.responseText:作为响应体返回的文本

xhr.responseXML:如果响应的内容类型是“text/xml”或者“application/xml”,这个属性中将保存包含着响应数据的XML DOM 文档

xhr.status:响应的HTTP状态

xhr.statusText:HTTP状态的说明

 

3)readyState 属性和 readystatechange 事件:

XHR对象有一个readyState 属性,表示请求/响应过程中的活动阶段,只要 readyState 变化就会触发一次 readystatechange 事件

readyState可取值:

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

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

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

3:接受,已经接受到部分响应数据

4:完成,已经接受到全部响应数据,而且数据可用

4)XMLHttpRequest.abort():如果该请求已被发出,XMLHttpRequest.abort() 方法将终止该请求。当一个请求被终止,它的 readyState 属性将被置为0( UNSENT )。

var xhr = createXHR();
xhr.onreadystatechange = function(){ // 必须在xhr.open()之前指定 onreadystatechange 事件处理程序,保证跨浏览器兼容
    if(xhr.readyState == 4){
        if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
            console.log("success");
            console.log(xhr.responseText);

        }else{
            console.log("failed");
            console.log(xhr);
        }
    }
}
xhr.open("get","./files/example.txt",true);
xhr.send(null);

 4、 HTTP 头部信息

每个http请求和响应都会带有相应的头部信息,xhr 对象提供了操作请求头和响应头的方法

浏览器发送ajax请求时可能会带上这些请求头:

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

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

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

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

Content-Type:请求发送内容的类型(大小写不敏感,可以不带字符集),"application/json; charset=utf-8","application/x-www-form-urlencoded; charset=utf-8","text/plain; charset=utf-8","text/html; charset=utf-8"

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

Cookie:当前页面的cookie,ajax会自动带上同源的cookie,不会带上不同源的cookie;可以通过前端设置withCredentials为true, 后端设置Header的方式让ajax自动带上不同源的cookie,但是这个属性对同源请求没有任何影响,会被自动忽略。

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

Referer:发请求页面的URI

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

 

可以使用 xhr.setRequestHeader("headerKey", "headerValue")设置请求头,需要在 open() 方法之后,send() 之前设置请求头。如果没有使用setRequestHeader()方法设置 Accept 头部信息,则会发送带有* / *的Accept头部。

可以使用 xhr.getResponseHeader("headerKey") 获取响应头

可以使用 xhr.getAllResponseHeaders() 获取所有响应头,多行文本

 

5、XMLHttpRequest 2级

1)FormData,可以序列化表单或创建于表单格式相同的数据,包括文件。经过它的数据可以使用 XMLHttpRequest.send() 方法送出,如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。

FormData.append():向 FormData 中添加新的属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值。

FormData.delete():从 FormData 对象里面删除一个键值对。

FormData.entries():返回一个包含所有键值对的iterator对象。

FormData.get():返回在 FormData 对象中与给定键关联的第一个值。

FormData.getAll():返回一个包含 FormData 对象中与给定键关联的所有值的数组。

FormData.has():返回一个布尔值表明 FormData 对象是否包含某些键。

FormData.keys():返回一个包含所有键的iterator对象。

FormData.set():给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值。

FormData.values():返回一个包含所有值的iterator对象。

        var data = new FormData();
        data.append("key","value"); // append() 方法可以添加任意个键值对

        data.set("key","value");
        data.set("key","value");

        var data1 = new FormData(document.forms[0]); // 可以直接使用表单数据穿件formdata
        data1.append("key","value");
        data1.append("key","value");
        console.log(data.getAll("key"));
        console.log(data1.getAll("key"));

 

2) XMLHttpRequest.timeout,表示该请求的最大请求时间(毫秒),超过该时间请求会自动结束。

在 xhr.open() 方法后且 send() 方法之前设置,默认值为 0,意味着没有超时。

超时并不应该用在一个 document environment (当javascript全局环境是window或iframe时,它被称为文档环境。全局环境是指没有外部环境的环境。) 中的同步 XMLHttpRequests  请求中,否则将会抛出一个 InvalidAccessError 类型的错误

当时间超时,会触发 xhr 对象的 timeout 事件 

var xhr = createXHR();
        xhr.onreadystatechange = function(){ // 必须在xhr.open()之前指定 onreadystatechange 事件处理程序,保证跨浏览器兼容
            if(xhr.readyState == 4){
               try {
                   if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
                       console.log("success");
                       console.log(xhr.responseText);

                   }else{
                       console.log("failed");
                       console.log(xhr);
                   }
               } catch (e) {
                   // 假设有 ontimeout 事件处理程序处理
                   // 当超时请求终止后,readyState 已经是 4 了,会进入 onreadystatechange 事件处理程序,但此时访问 status 属性会导致错误,所使用try-catch
               }

            }
        }
        xhr.open("get","./files/example.txt",true);

        xhr.timeout = 1000; // 毫秒
        xhr.ontimeout = function(e){
            console.log("timeout");
        };

        xhr.send(null);

 

 3)XMLHttpRequest.overrideMimeType(mimeType):指定一个MIME类型用于替代服务器指定的类型,使服务端响应信息中传输的数据按照该指定MIME类型处理

如果服务器没有指定一个Content-Type 头, XMLHttpRequest 默认MIME类型为"text/xml". 如果接受的数据不是有效的XML,将会出现格”格式不正确“的错误。你能够通过调用 overrideMimeType() 指定各种类型来避免这种情况

xhr = new XMLHttpRequest();
xhr.overrideMimeType("text/plain");
xhr.addEventListener("load", callback, false);
xhr.open("get", url);
xhr.send(null);

4)XMLHttpRequest 请求的事件

error:请求错误

load:收到完整响应数据(成功),XMLHttpRequest.onload 事件处理程序可以替代  XMLHttpRequest.onreadystatechange,可以不用检查 readyState 属性。

loadend:请求结束(成功,失败,终止)

loadstart:收到响应数据第一个字节

progress:正在接收数据,progress 事件会在浏览器接受新数据期间周期性的触发(用于文件下载进度)。onprogress事件处理程序会接收到一个event对象,该事件对象包含的属性

lengthComputable  Boolean 表示进度信息是否可用. 只读.
loaded 
unsigned long (long) 已经传输的字节数。这不包括头和其他开销,只包括内容本身。只读。
total
unsigned long (long) 传输内容的总字节数,如果总字节数未知,这个数字为0

5)XMLHttpRequest.upload :返回一个 XMLHttpRequestUpload对象,用来表示上传的进度。

可以被绑定在upload对象上的事件监听器如下:

事件 相应属性的信息类型
onloadstart 获取开始
onprogress 数据传输进行中,处理程序中的event的属性也包含lengthComputable, loaded, total
onabort 获取操作终止
onerror 获取失败
onload 获取成功
ontimeout 获取操作在用户规定的时间内未完成
onloadend 获取完成(不论成功与否)
 <style media="screen">
    .parent {width:500px; height:20px; border:1px solid black;}
    .child {width:0; height:100%; background:green;}
    </style>
    <script>
    window.onload=function (){
      let oF=document.getElementById('f1');
      let oBtn=document.getElementById('btn1');

      oBtn.onclick=function (){
        let data=new FormData();

        Array.from(oF.files).forEach(file=>{
          data.append('f1', file);
        });
                let oAjax=new XMLHttpRequest();

        //POST
        oAjax.open('POST', `http://localhost:8080/api`, true);

        oAjax.onprogress=function (ev){
          console.log(ev);
        };

        oAjax.upload.addEventListener('progress', function (ev){
          let oChild=document.getElementsByClassName('child')[0];
          oChild.style.width=100*ev.loaded/ev.total+'%';
        }, false);

        oAjax.send(data);
      };
    };
    </script>
  </head>
  <body>
    <div class="parent">
      <div class="child">

      </div>
    </div>
    <input type="file" id="f1" multiple /><br>
    <input type="button" value="提交" id="btn1">
  </body>

 6)XMLHttpRequest.withCredentials  属性是一个Boolean类型,默认值是false

 表示是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。

如果来自其他域的XMLHttpRequest请求在发送之前,未设置withCredentials 为true,那么就不能为那个域设置cookie值。而通过设置withCredentials 为true获得的第三方cookies,将会依旧享受同源策略

 

7) XMLHttpRequest.responseType

属性 responseType 是一个枚举字符串值,可设置或获取响应中包含的数据类型。

可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' , 默认是 ‘text’, 如果指定为空字符串,等同于 'text'
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
posted @ 2019-06-21 17:58  zhanglw  阅读(257)  评论(0)    收藏  举报