javascript高级编程系列 - 使用XMLHttpRequest发送请求

通过XMLHttpRequest发送GET请求

// 创建XMLHttpRequest实例对象
const xhr = new XMLHttpRequest();
//  监听通信状态
xhr.onreadystatechange = function(){
  // 请求结束,处理服务器返回的数据
  if (xhr.readyState === 4){
    // http状态码为200表示成功返回
    if (xhr.status === 200){
      console.log(xhr.responseText);
    } else {
      console.error(xhr.statusText);
    }
  }
  else {
    // 显示正在加载中...
  }
};
// 监听通信出错时的处理函数
xhr.onerror = function (e) {
  console.error(xhr.statusText);
};
// 添加发送请求的参数: 请求方法,url, 是否异步
xhr.open('GET', '/endpoint', true);
// 发送实际请求, GET请求参数为null
xhr.send(null);

通过XMLHttpRequest发送POST请求

var xhr = new XMLHttpRequest();
var url = "your_endpoint_url"; 

// 将js对象转化为json字符串
var data = JSON.stringify({
  key1: "value1",
  key2: "value2"
 });

xhr.open("POST", url, true);
// 设置请求头
xhr.setRequestHeader("Content-Type", "application/json");

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
    // 请求成功
    var response = JSON.parse(xhr.responseText);
    console.log(response);
  }
};
// 将json字符串作为参数传入
xhr.send(data);

XMLHttpRequest对象的实例方法

  1. XMLHttpRequest.open()
    XMLHttpRequest.open()方法用于指定 HTTP 请求的参数,或者说初始化 XMLHttpRequest 实例对象。它一共可以接受五个参数。
  • method:表示 HTTP 动词方法,比如GET、POST、PUT、DELETE、HEAD等。
  • url: 表示请求发送目标 URL。
  • async: 布尔值,表示请求是否为异步,默认为true。如果设为false,则send()方法只有等到收到服务器返回了结果,才会进行下一步操作。该参数可选。由于同步 AJAX 请求会造成浏览器失去响应,许多浏览器已经禁止在主线程使用,只允许 Worker 里面使用。所以,这个参数轻易不应该设为false。
  • user:表示用于认证的用户名,默认为空字符串。该参数可选。
  • password:表示用于认证的密码,默认为空字符串。该参数可选。
  1. XMLHttpRequest.send()
    XMLHttpRequest.send()方法用于实际发出 HTTP 请求。它的参数是可选的,如果不带参数,就表示 HTTP 请求只有一个 URL,没有数据体,典型例子就是 GET 请求;如果带有参数,就表示除了头信息,还带有包含具体数据的信息体,典型例子就是 POST 请求。
  • GET 请求
var xhr = new XMLHttpRequest();
xhr.open('GET',
  'http://www.example.com/?id=' + encodeURIComponent(id),
  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()方法调用之前设定。
send方法的参数就是发送的数据。多种格式的数据,都可以作为它的参数。

void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(String data);
void send(FormData data);
  • 发送表单数据
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);
  1. XMLHttpRequest.setRequestHeader()
    XMLHttpRequest.setRequestHeader()方法用于设置浏览器发送的 HTTP 请求的头信息。该方法必须在open()之后、send()之前调用。如果该方法多次调用,设定同一个字段,则每一次调用的值会被合并成一个单一的值发送。
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));
  1. XMLHttpRequest.overrideMimeType()
    XMLHttpRequest.overrideMimeType()方法用来指定 MIME 类型,覆盖服务器返回的真正的 MIME 类型,从而让浏览器进行不一样的处理。举例来说,服务器返回的数据类型是text/xml,由于种种原因浏览器解析不成功报错,这时就拿不到数据了。为了拿到原始数据,我们可以把 MIME 类型改成text/plain,这样浏览器就不会去自动解析,从而我们就可以拿到原始文本了。
xhr.overrideMimeType('text/plain');
  1. XMLHttpRequest.getResponseHeader()
    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();
  1. XMLHttpRequest.getAllResponseHeaders()
    XMLHttpRequest.getAllResponseHeaders()方法返回一个字符串,表示服务器发来的所有 HTTP 头信息。格式为字符串,每个头信息之间使用CRLF分隔(回车+换行),如果没有收到服务器回应,该属性为null。如果发生网络错误,该属性为空字符串。
  • 服务器返回的数据
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
  • 处理数据存储到对象中
var xhr = new XMLHttpRequest();
xhr.open('GET', 'foo.txt', true);
xhr.send();
xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    var headers = xhr.getAllResponseHeaders();
    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"
  }
}
  1. XMLHttpRequest.abort()
    XMLHttpRequest.abort()方法用来终止已经发出的 HTTP 请求。调用这个方法以后,readyState属性变为4,status属性变为0。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.example.com/page.php', true);
setTimeout(function () {
  if (xhr) {
    xhr.abort();
    xhr = null;
  }
}, 5000);

XMLHttpRequest对象的实例属性

  1. readyState 属性
0 - 表示 XMLHttpRequest 实例已经生成,但是实例的open()方法还没有被调用。
1 - 表示open()方法已经调用,但是实例的send()方法还没有调用,仍然可以使用实例的setRequestHeader()方法,设定 HTTP 请求的头信息。
2 - 表示实例的send()方法已经调用,并且服务器返回的头信息和状态码已经收到。
3 - 表示正在接收服务器传来的数据体(body 部分)。这时,如果实例的responseType属性等于text或者空字符串,responseText属性就会包含已经收到的部分信息。
4 - 表示服务器返回的数据已经完全接收,或者本次接收已经失败。
  1. onreadystatechange事件处理器
    onreadystatechange属性指向一个监听函数。readystatechange事件发生时(实例的readyState属性变化),就会执行这个属性。

  2. responseType 返回数据类型
    responseType属性是一个字符串,表示服务器返回数据的类型。这个属性是可写的,可以在调用open()方法之后、调用send()方法之前,设置这个属性的值,告诉服务器返回指定类型的数据。
    XMLHttpRequest.responseType属性可以等于以下值。

  • ""(空字符串):等同于text,表示服务器返回文本数据。
  • "arraybuffer":ArrayBuffer 对象,表示服务器返回二进制数组。
  • "blob":Blob 对象,表示服务器返回二进制对象。
  • "document":Document 对象,表示服务器返回一个文档对象。
  • "json":JSON 对象。
  • "text":字符串。
  1. response属性 返回数据体
    response属性表示服务器返回的数据体(即 HTTP 回应的 body 部分)。它可能是任何数据类型,比如字符串、对象、二进制对象等等,具体的类型由XMLHttpRequest.responseType属性决定。该属性只读。
  • 返回数据类型为二进制对象
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();
  • 返回类型为二进制数组
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
  var uInt8Array = new Uint8Array(this.response);
  for (var i = 0, len = uInt8Array.length; i < len; ++i) {
    // var byte = uInt8Array[i];
  }
};
xhr.send();
  1. responseText 属性
    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);
  1. responseXML 属性
    responseXML属性返回从服务器接收到的 HTML 或 XML 文档对象,该属性为只读。如果本次请求没有成功,或者收到的数据不能被解析为 XML 或 HTML,该属性等于null。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.responseType = 'document';
xhr.overrideMimeType('text/xml');
xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseXML);
  }
};
xhr.send(null);
  1. responseURL 属性
    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);
  1. status & statusText
    status属性返回一个整数,表示服务器回应的 HTTP 状态码。
    statusText属性返回一个字符串,表示服务器发送的状态提示。
  • 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,服务器发生错误
  1. timeout & ontimeout
    timeout属性返回一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。如果该属性等于0,就表示没有时间限制。
    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);
  1. 事件监听属性
  • onloadstart:loadstart 事件(HTTP 请求发出)的监听函数
  • onprogress:progress事件(正在发送和加载数据)的监听函数
  • onabort:abort 事件(请求中止,比如用户调用了abort()方法)的监听函数
  • onerror:error 事件(请求失败)的监听函数
  • onload:load 事件(请求成功完成)的监听函数
  • ontimeout:timeout 事件(用户指定的时限超过了,请求还未完成)的监听函数
  • onloadend:loadend 事件(请求完成,不管成功或失败)的监听函数
xhr.onload = function() {
 var responseText = xhr.responseText;
 console.log(responseText);
 // process the response.
};
xhr.onabort = function () {
  console.log('The request was aborted');
};
xhr.onprogress = function (event) {
  console.log(event.loaded);
  console.log(event.total);
};
xhr.onerror = function() {
  console.log('There was an error!');
};
  1. withCredentials (发送和设置用户信息)
    withCredentials属性是一个布尔值,表示跨域请求时,用户信息(比如 Cookie 和认证的 HTTP 头信息)是否会包含在请求之中,默认为false. 为了让这个属性生效,服务器必须显式返回Access-Control-Allow-Credentials这个头信息。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
  1. upload 属性
    XMLHttpRequest 不仅可以发送请求,还可以发送文件,这就是 AJAX 文件上传。发送文件以后,通过XMLHttpRequest.upload属性可以得到一个对象,通过观察这个对象,可以得知上传的进展。
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 实例的事件

  1. readyStateChange 事件
    readyState属性的值发生改变,就会触发 readyStateChange 事件。
    我们可以通过onReadyStateChange属性,指定这个事件的监听函数,对不同状态进行不同处理。尤其是当状态变为4的时候,表示通信成功,这时回调函数就可以处理服务器传送回来的数据。

  2. 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();
  1. load 事件、error 事件、abort 事件
    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('用户取消接收');
}
  1. loadend 事件
    abort、load和error这三个事件,会伴随一个loadend事件,表示请求结束,但不知道其是否成功。
xhr.addEventListener('loadend', loadEnd);
function loadEnd(e) {
  console.log('请求结束,状态未知');
}
  1. timeout 事件
    服务器超过指定时间还没有返回结果,就会触发 timeout 事件.

参考:https://www.bookstack.cn/read/javascript-tutorial/docs-bom-xmlhttprequest.md

posted @ 2024-04-25 17:46  箫笛  阅读(230)  评论(0编辑  收藏  举报