BOM 浏览器对象模型_XMLHttpRequest 对象

XMLHttpRequest 对象php

浏览器与服务器之间,采用 HTTP 协议 通讯。html

用户在浏览器地址栏键入一个网址,或者经过网页表单向服务器提交内容,这时浏览器就会向服务器发出 HTTP 请求json

AJAX跨域

2005.02 提出的概念 ---- Asynchronous JavaScript and XML数组

经过 JavaScript 的异步通讯,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页浏览器

  • 一般概念:

JavaScript 脚本发起 HTTP 通讯的代名词服务器

也就是说,只要用脚本发起通讯,就能够叫作 AJAX 通讯
网络

  • W3C 也在2006年发布了它的国际标准

1. 建立 XMLHttpRequest 实例app

var xhr = new XMLHttpRequest();异步

 

2. 发出 HTTP 请求

// 向指定的服务器网址,发出 GET 请求

xhr.open('GET', 'http://www.example.com/page.php', true);

3. 接收服务器传回的数据

// 监听通讯状态(readyState属性)的变化

xhr.onreadystatechange = handleStateChange;

function handleStateChange(){... ...}

4. 更新网页数据

// 一旦拿到服务器返回的数据,AJAX 不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在作的事情

归纳为: AJAX 经过原生的 XMLHttpRequest 对象发出 HTTP 请求,获得服务器返回的数据后,再进行处理

注意: 

如今,服务器返回的都是 JSON 格式的数据,XML 格式已通过时了

AJAX 这个名字已经成了一个通用名词,字面含义已经消失了

XMLHttpRequest 对象是 AJAX 的主要接口,用于浏览器与服务器之间的通讯

不止 XML 和 Http,实际可使用多种协议(如fileftp)发送任何格式的数据(字符串、二进制)

AJAX 只能向同源网址(协议域名端口都相同)发出 HTTP 请求,若是发出跨域请求,就会报错

使用实例的 abort() 方法,终止 XMLHttpRequest 请求,也会形成 readyState 属性变化,致使调用  XMLHttpRequest.onreadystatechange 属性

XMLHttpRequest 的实例属性

  • XMLHttpRequest.readyState ---- 整数,表示实例对象的当前状态

该属性只读。它可能返回如下值。

0    表示 XMLHttpRequest 实例已经生成,可是实例的 open() 方法尚未被调用。
1    表示 open() 方法已经调用,可是实例的 send() 方法尚未调用

仍然可使用实例的 setRequestHeader() 方法,设定 HTTP 请求的头信息。

2    表示实例的 send() 方法已经调用,而且服务器返回的头信息和状态码已经收到。
3    表示正在接收服务器传来的数据体(body 部分)

这时,若是实例的 responseType 属性等于 text 或者空字符串

responseText 属性就会包含已经收到的部分信息。

4    表示服务器返回的数据已经彻底接收,或者本次接收已经失败

  • var xhr = new XMLHttpRequest();
    
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        handler(xhr.response);
     } }
  • XMLHttpRequest.response ---- 服务器返回的数据体(即 HTTP 回应的 body 部分)

该属性只读

它多是任何数据类型,好比字符串、对象、二进制对象等等

  • 具体的类型由 XMLHttpRequest.responseType ---- 字符串 属性决定。

表示服务器返回数据的类型。

这个属性是可写的,能够在调用 open() 方法以后、调用 send() 方法以前,设置这个属性的值,告诉服务器返回指定类型的数据

若是 responseType 设为空字符串,就等同于默认值 text

 

  • "text"        字符串
  • ""(空字符串)        等同于text,表示服务器返回文本数据

适合大多数状况,并且直接处理文本也比较方便

 

  • "arraybuffer"        ArrayBuffer 对象,表示服务器返回二进制数组
  • var xhr = new XMLHttpRequest();
    xhr.open('GET', '/path/to/image.png', true);
    xhr.responseType = 'blob';
    
    xhr.onload = function(e) {
      if (this.status === 200) {
        var blob = new Blob([xhr.response], {type: 'image/png'});
        // 或者
        var blob = xhr.response;
      }
    };
    
    xhr.send();
  • "blob"        Blob 对象,表示服务器返回二进制对象

适合读取二进制数据,好比图片文件

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', '/path/to/image.png', true);
    xhr.responseType = 'blob';
    
    xhr.onload = function(e) {
      if (this.status === 200) {
        var blob = new Blob([xhr.response], {type: 'image/png'});
        // 或者
        var blob = xhr.response;
      }
    };
    
    xhr.send();
  • "document"        Document 对象,表示服务器返回一个文档对象

适合返回 HTML / XML 文档的状况

这意味着,对于那些打开 CORS 的网站,能够直接用 Ajax 抓取网页

而后不用解析 HTML 字符串,直接对抓取回来的数据进行 DOM 操做

  • "json"        JSON 对象

若是将这个属性设为json,浏览器就会自动对返回数据调用 JSON.parse() 方法

也就是说,从 xhr.response 属性(注意,不是xhr.responseText属性)获得的不是文本,而是一个 JSON 对象

 

若是本次请求没有成功或者数据不完整,该属性等于null

可是,若是 responseType 属性等于 text 或空字符串

在请求没有结束以前(readyState 等于 3 的阶段)

XMLHttpRequest.response 属性包含服务器已经返回的部分数据

  • XMLHttpRequest.responseText --- 从服务器接收到的字符串

该属性为只读

只有 HTTP 请求完成接收之后,该属性才会包含完整的数据

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', '/server', true);
    
    xhr.responseType = 'text';
    xhr.onload = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
      }
    };
    
    xhr.send(null);

XMLHttpRequest.responseXML ---- 直接解析后的文档 DOM 树

生效的前提是 HTTP 回应的 Content-Type 头信息等于 text/xmlapplication/xml

在发送请求前,XMLHttpRequest.responseType 属性要设为 document

若是 HTTP 回应的 Content-Type 头信息不等于 text/xml 和 application/xml ,

可是又想从 responseXML 拿到数据(即把数据按照 DOM 格式解析),

那么须要手动调用 XMLHttpRequest.overrideMimeType() 方法,强制进行 XML 解析

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', '/server', true);
    
    xhr.responseType = 'document';
    xhr.overrideMimeType('text/xml');    // 强制进行 XML 解析
    
    xhr.onload = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseXML);    // 获得的数据,是直接解析后的文档 DOM 树
      }
    };
    
    xhr.send(null);

返回从服务器接收到的 HTML 或 XML 文档对象,该属性为只读。

若是本次请求没有成功,或者收到的数据不能被解析为 XML 或 HTML,该属性等于 null

XMLHttpRequest.responseURL ---- 字符串,表示发送数据的服务器的网址

  • var xhr = new XMLHttpRequest(
    xhr.open('GET', 'http://example.com/test', true);
    xhr.onload = function () {
        // 返回 http://example.com/test
        console.log(xhr.responseURL);
    };
    xhr.send(null);

这个属性的值 与 open()方 法指定的请求网址不必定相同

若是服务器端发生跳转,这个属性返回最后实际返回数据的网址

另外,若是原始 URL 包括锚点(fragment),该属性会把锚点剥离

XMLHttpRequest.status ---- 整数,表示服务器回应的 HTTP 状态码

通常来讲,若是通讯成功的话,这个状态码是200;

若是服务器没有返回状态码,那么这个属性默认是 200。

请求发出以前,该属性为 0。该属性只读

 

  • 200        OK,访问正常
  • 301        Moved Permanently,永久移动
  • 302        Moved temporarily,暂时移动
  • 304        Not Modified,未修改
  • 307        Temporary Redirect,暂时重定向
  • 401        Unauthorized,未受权
  • 403        Forbidden,禁止访问
  • 404        Not Found,未发现指定网址
  • 500        Internal Server Error,服务器发生错误

XMLHttpRequest.statusText ---- 返回一个字符串,表示服务器发送的状态提示

该属性只读,包含整个状态信息,好比 “OK” 和 “Not Found”

在请求发送以前(即调用 open() 方法以前),该属性的值是空字符串

若是服务器没有返回状态提示,该属性的值默认为"“OK”

XMLHttpRequest.timeout ---- 整数,表示多少毫秒后,若是请求仍然没有获得结果,就会自动终止

若是该属性等于 0 ,就表示没有时间限制

XMLHttpRequestEventTarget.ontimeout ---- 用于设置一个监听函数,若是发生 timeout 事件,就会执行这个监听函数

  • var xhr = new XMLHttpRequest();
    var url = '/server';
    
    xhr.ontimeout = function () {
      console.error('The request for ' + url + ' timed out.');
    };
    
    xhr.onload = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                // 处理服务器返回的数据
            } else {
                console.error(xhr.statusText);
            }
        }
    };
    
    xhr.open('GET', url, true);
    
    // 指定 10 秒钟超时
    xhr.timeout = 10 * 1000;
    xhr.send(null);

XMLHttpRequest.withCredentials ---- 布尔值,表示跨域请求时,用户信息(好比 Cookie 和认证的 HTTP 头信息)是否会包含在请求之中

默认为 false,即向 example.com 发出跨域请求时,不会发送example.com设置在本机上的 Cookie(若是有的话)

withCredentials属性打开的话,跨域请求不只会发送 Cookie,还会设置远程主机指定的 Cookie

若是须要跨域 AJAX 请求发送 Cookie,须要 withCredentials 属性设为true。注意,同源的请求不须要设置这个属性

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://example.com/', true);
    xhr.withCredentials = true;
    xhr.send(null);

    为了让这个属性生效,服务器必须显式返回Access-Control-Allow-Credentials这个头信息

  • Access-Control-Allow-Credentials: true

XMLHttpRequest 事件监听函数

 

.onloadstart        loadstart 事件        (HTTP 请求发出)的监听函数
.onprogress        progress 事件        (正在发送和加载数据)的监听函数
.onabort        abort 事件        (请求停止,好比用户调用了abort()方法)的监听函数
.onerror        error 事件        (请求失败)的监听函数

注意,若是发生网络错误(好比服务器没法连通),onerror 事件没法获取报错信息

也就是说,可能没有错误对象,因此这样只能显示报错的提示

.onload        load 事件        (请求成功完成)的监听函数
.ontimeout        timeout 事件        (用户指定的时限超过了,请求还未完成)的监听函数
.onloadend        loadend 事件        (请求完成,无论成功或失败)的监听函数

全部这些监听函数里面,只有 progress 事件的监听函数有事件对象参数,该对象有三个属性

loaded        返回 已经传输的数据量

total        属性返回 总的数据量

lengthComputable        返回一个布尔值,表示加载的进度是否能够计算

AJAX 文件上传

发送文件之后,经过 XMLHttpRequest.upload 属性能够获得一个对象,经过观察这个对象,能够得知上传的进展

主要方法就是监听这个对象的各类事件:loadstart、loadend、load、abort、error、progress、timeout

假定网页上有一个 <progress> 元素

  • <progress min="0" max="100" value="0">0% complete</progress>

    指定progress事件的监听函数,便可得到上传的进度

  • function upload(blobOrFile) {
      var xhr = new XMLHttpRequest();
      xhr.open('POST', '/server', true);
      xhr.onload = function (e) {};
    
      var progressBar = document.querySelector('progress');
      xhr.upload.onprogress = function (e) {
        if (e.lengthComputable) {
          progressBar.value = (e.loaded / e.total) * 100;
          // 兼容不支持 <progress> 元素的老式浏览器
          progressBar.textContent = progressBar.value;
        }
      };
    
      xhr.send(blobOrFile);
    }
    
    upload(new Blob(['hello world'], {type: 'text/plain'}));

XMLHttpRequest 的实例方法

XMLHttpRequest.open()

用于指定 HTTP 请求的参数,或者说初始化 XMLHttpRequest 实例对象。

它一共能够接受五个参数

  • void open( string method, // method:表示 HTTP 动词方法,好比 GET、POST、PUT、DELETE、HEAD等。 string url, // 表示请求发送目标 URL optional boolean async, // 布尔值,表示请求是否为异步,默认为 true。该参数可选。 // 若是设为 false,则 send() 方法只有等到收到服务器返回告终果,才会进行下一步操做。 // 因为同步 AJAX 请求会形成浏览器失去响应,许多浏览器已经禁止在主线程使用,只容许 Worker 里面使用。 // 因此,这个参数轻易不该该设为 false optional string user, // 表示用于认证的用户名,默认为空字符串。该参数可选 optional string password // 表示用于认证的密码,默认为空字符串。该参数可选 );

若是对使用过 open() 方法的 AJAX 请求,再次使用这个方法,等同于调用 abort(),即终止请求

XMLHttpRequest.send()

用于实际发出 HTTP 请求

它的参数是可选的,

若是不带参数,就表示 HTTP 请求只有一个 URL,没有数据体,典型例子就是 GET 请求

  • var xhr = new XMLHttpRequest();
    xhr.open('GET',
        'http://www.example.com/?id=' + encodeURIComponent(id),    // GET请求的参数,做为查询字符串附加在 URL 后面
        true
    );
    xhr.send(null);

若是带有参数,就表示除了头信息,还带有包含具体数据的信息体,典型例子就是 POST 请求

  • var xhr = new XMLHttpRequest();
    var data = 'email='
      + encodeURIComponent(email)
      + '&password='
      + encodeURIComponent(password);
    
    xhr.open('POST', 'http://www.example.com', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(data);    

    // 注意,XMLHttpRequest 全部的监听事件,都必须在 send() 方法调用以前设定

 

参数就是发送的数据。多种格式的数据,均可以做为它的参数

void send();
void send(ArrayBufferView data);
void send(Blob data);    // 若是发送二进制数据,最好是发送ArrayBufferView或Blob对象,这使得经过 Ajax 上传文件成为可能
void send(Document data);    // 若是send()发送 DOM 对象,在发送以前,数据会先被串行化
void send(String data);
void send(FormData data);

  • 发送表单数据的例子
  • 1
  • var formData = new FormData();
    
    formData.append('username', '张三');
    formData.append('email', 'zhangsan@example.com');
    formData.append('birthDate', 1940);
    
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/register');
    xhr.send(formData);
  • 与发送下面的 表单数据 是同样的
  • <form id='registration' name='registration' action='/register'>
      <input type='text' name='username' value='张三'>
      <input type='email' name='email' value='zhangsan@example.com'>
      <input type='number' name='birthDate' value='1940'>
      <input type='submit' onclick='return sendForm(this.form);'>
    </form>
  • 使用 FormData 对象加工表单数据,而后再发送
  • function sendForm(form) {
      var formData = new FormData(form);
      formData.append('csrf', 'e69a18d7db1286040586e6da1950128c');
    
      var xhr = new XMLHttpRequest();
      xhr.open('POST', form.action, true);
      xhr.onload = function() {
        // ...
      };
      xhr.send(formData);
    
      return false;
    }
    
    var form = document.querySelector('#registration');
    sendForm(form);

XMLHttpRequest.setRequestHeader()

用于设置浏览器发送的 HTTP 请求的头信息。

  • xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
    xhr.send(JSON.stringify(data));

     

  • 首先设置头信息 Content-Type,表示发送 JSON 格式的数据

  • 而后设置 Content-Length,表示数据长度

  • 最后发送 JSON 数据。

该方法必须在open()以后、send()以前调用。

该方法接受两个参数

第一个参数是字符串,表示头信息的字段名

第二个参数是字段值

若是该方法屡次调用,设定同一个字段,则每一次调用的值会被合并成一个单一的值发送。

XMLHttpRequest.overrideMimeType()

用来指定 MIME 类型,覆盖服务器返回的真正的 MIME 类型,从而让浏览器进行不同的处理。

举例来讲,服务器返回的数据类型是 text/xml,因为种种缘由浏览器解析不成功报错,这时就拿不到数据了。

为了拿到原始数据,咱们能够把 MIME 类型改为 text/plain,这样浏览器就不会去自动解析,从而咱们就能够拿到原始文本了

  • xhr.overrideMimeType('text/plain')

修改服务器返回的数据类型,不是正常状况下应该采起的方法。

若是但愿服务器返回指定的数据类型,能够用 responseType 属性告诉服务器,就像下面的例子。

只有在服务器没法返回某种数据类型时,才使用 overrideMimeType() 方法

  • var xhr = new XMLHttpRequest();
    xhr.onload = function(e) {
        var arraybuffer = xhr.response;
        // ...
    }
    xhr.open('GET', url);
    xhr.responseType = 'arraybuffer';
    xhr.send();

XMLHttpRequest.getResponseHeader()

返回 HTTP 头信息指定字段的值

若是尚未收到服务器回应或者指定字段不存在,返回 null。

  • function getHeaderTime() {
        console.log(this.getResponseHeader("Last-Modified"));
    }
    
    var xhr = new XMLHttpRequest();
    xhr.open('HEAD', 'yourpage.html');
    xhr.onload = getHeaderTime;
    xhr.send();

该方法的参数不区分大小写

若是有多个字段同名,它们的值会被链接为一个字符串,每一个字段之间使用 “逗号+空格” 分隔

XMLHttpRequest.getAllResponseHeaders()

返回一个字符串,表示服务器发来的全部 HTTP 头信息。

格式为字符串,每一个头信息之间使用 CRLF 分隔(回车+换行)

若是没有收到服务器回应,该属性为null

若是发生网络错误,该属性为空字符串

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', 'foo.txt', true);
    xhr.send();
    
    xhr.onreadystatechange = function () {
        if (this.readyState === 4) {
            var headers = xhr.getAllResponseHeaders();
        }
    }

    上面代码用于获取服务器返回的全部头信息。它多是下面这样的字符串

  • date                          Fri, 08 Dec 2017 21:04:30 GMT\r\n
    content-encoding ------------ gzip\r\n
    x-content-type-options        nosniff\r\n
    server ---------------------- meinheld/0.6.1\r\n
    x-frame-options                DENY\r\n
    content-type --------------- text/html; charset=utf-8\r\n
    connection                   keep-alive\r\n
    strict-transport-security -- max-age=63072000\r\n
    vary                         Cookie, Accept-Encoding\r\n
    content-length ------------- 6502\r\n
    x-xss-protection             1; mode=block\r\n

而后,对这个字符串 header 进行处理

  • var arr = headers.trim().split(/[\r\n]+/);
    var headerMap = {};
    
    arr.forEach(function (line) {
        var parts = line.split(': ');
        var header = parts.shift();
        var value = parts.join(': ');
        headerMap[header] = value;
    });
    
    headerMap['content-length']    // "6502"

XMLHttpRequest.abort()

用来终止已经发出的 HTTP 请求。

调用这个方法之后,readyState 属性变为 4,status 属性变为0

举个例子: 发出5秒以后,终止一个 AJAX 请求

  • var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://www.example.com/page.php', true);
    setTimeout(function () {
        if (xhr) {
            xhr.abort();
            xhr = null;
        }
    }, 5000);

重要的事件

readyStateChange 事件

readyState 属性的值发生改变,就会触发 readyStateChange 事件

咱们能够经过onReadyStateChange属性,指定这个事件的监听函数,对不一样状态进行不一样处理

尤为是当状态变为 4 的时候,表示通讯成功,这时回调函数就能够处理服务器传送回来的数据

progress 事件

上传文件时,XMLHTTPRequest 实例对象自己和实例的 upload 属性,都有一个 progress 事件,会不断返回上传的进度

  • var xhr = new XMLHttpRequest();
    
    function updateProgress (oEvent) {
        if (oEvent.lengthComputable) {
            var percentComplete = oEvent.loaded / oEvent.total;
        } else {
            console.log('没法计算进展');
        }
    }
    
    xhr.addEventListener('progress', updateProgress);
    
    xhr.open();

load  事件      表示服务器传来的数据接收完毕

error 事件       表示请求出错

abort 事件       表示请求被中断(好比用户取消请求)

  • var xhr = new XMLHttpRequest();
    
    xhr.addEventListener('load', transferComplete);
    xhr.addEventListener('error', transferFailed);
    xhr.addEventListener('abort', transferCanceled);
    
    xhr.open();
    
    function transferComplete() {
        console.log('数据接收完毕');
    }
    
    function transferFailed() {
        console.log('数据接收出错');
    }
    
    function transferCanceled() {
        console.log('用户取消接收');
    }

Navigator.sendBeacon() 用户卸载网页的时候,有时须要向服务器发一些数据

XMLhttpRequest对象是异步发送,极可能在它即将发送的时候,页面已经卸载了

这个方法仍是异步发出请求,可是请求与当前页面脱钩,做为浏览器的任务,所以能够保证会把数据发出去,不拖延卸载流程

  • window.addEventListener('unload', logData, false);
    
    function logData() {
        navigator.sendBeacon('/log', analyticsData);
    }

第一个参数是目标服务器的 URL

第二个参数是所要发送的数据(可选),能够是任意类型(字符串、表单对象、二进制对象等等)

成功发送数据 返回 true,不然返回为 false

发送数据的 HTTP 方法是 POST,能够跨域,相似于表单提交数据。它不能指定回调函数

  • // HTML 代码以下
    // <body onload="analytics('start')" onunload="analytics('end')">
    
    function analytics(state) {
        if (!navigator.sendBeacon) 
    return; var URL = 'http://example.com/analytics'; var data = 'state=' + state + '&location=' + window.location; navigator.sendBeacon(URL, data); }
相关文章
相关标签/搜索