浏览器中的XMLHttpRequest和Fetch

浏览器中的XMLHttpRequest和Fetch

1 年前

XMLHttpRequest

是什么

使用 XMLHttpRequest 在脚本中请求特定的url,获取数据。

readyState

请求的状态码

状态 描述
0 UNSENT XMLHttpRequest被创建,且open() 方法未调用
1 OPENED open() 已经被调用
2 HEADERS_RECEIVED send() 已经被调用,且响应头部和状态已经获得
3 LOADING 下载中,response已经包含部分数据
4 DONE 请求完成

onreadystatechange

readyState 属性发生变化时,会调用 onreadystatechange 函数

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
    // 0 1 ""
    // 200 2 ""
    // 200 3 "第一次输出"
    // 200 3 "第一次输出延迟2秒后的输出"
    // 200 3 "第一次输出延迟2秒后的输出延迟4秒后的输出"
    // 200 4 "第一次输出延迟2秒后的输出延迟4秒后的输出"
    console.log(this.status, this.readyState, this.response);
xhr.open('GET', url);
xhr.send();

status

返回的状态码

statusText

返回的响应状态

response

响应内容,数据类型通过 responseType 定义

responseType

描述
为空时,默认和text相同
arraybuffer response是一个 ArrayBuffer 对象
blob response是一个 Blob 对象
document response是一个HTML Document 或者 XML Document
json response是一个js对象
text response是一个DOMString`对象

timeout

设置请求超时时间,当超时发生后,请求的 readyState 会变为4(DONE), status 由已接受到的200变为0, respose 置为空。触发timeout事件。

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
    // 0 1 ""
    // 200 2 ""
    // 200 3 "第一次输出"
    // 0 4 ""
    console.log(this.status, this.readyState, this.response);
xhr.addEventListener('timeout', function () {
    // timeout 0 4
    console.log('timeout', this.status, this.readyState, this.response);
xhr.addEventListener('error', function () {
    console.log('error', this.status, this.readyState, this.response);
xhr.open('GET', url);
xhr.timeout = 1000;
xhr.send();

withCredentials

默认值是 false ,在跨域请求时,不携带 cookie ,且响应的 Set-Cookie 不生效。设置为 true 时,跨域请求会带上 cookie ,且响应的 Set-Cookie 会生效。对同源请求,该属性不生效。

// 验证withCredentials可以发送cookies、设置cookies
var xhr = new XMLHttpRequest();
var url = 'http://localhost:8090/setcookie?c=' + encodeURIComponent('random=' + Math.random());
xhr.onreadystatechange = function () {
    console.log(this.status, this.readyState, this.response);
xhr.open('GET', url);
xhr.withCredentials = true;
xhr.send();
// 请求完成后,在开发者面板可以看到,域名localhost:8090下的cookies中存在由响应设置的random值

响应中的 Set-Cookie :

请求头中带有 cookie :

域名下的 cookie 被成功设置

注意

  1. withCredentials 依然要遵循浏览器的安全策略,不同域名下的cookie是隔离的,不能相互访问对方域名下的 cookie

2. 响应头需要设置 Access-Control-Allow-Origin Access-Control-Allow-Credentials ,否则跨域请求会失败

self.set_header('Access-Control-Allow-Origin', 'http://localhost:8210')
self.set_header('Access-Control-Allow-Credentials', 'true') 

setRequestHeader

设置HTTP请求头,需要在 open() 函数调用和 send() 函数调用之间调用。 考虑到安全问题,浏览器会禁止用户设置某些请求头。被禁止的请求头包括

  • Proxy- 开头
  • Sec- 开头
  • Accept-Charset
  • Accept-Encoding
  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Connection
  • Content-Length
  • Cookie
  • Cookie2
  • Date
  • DNT
  • Expect
  • Feature-Policy
  • Host
  • Keep-Alive
  • Origin
  • Proxy-
  • Sec-
  • Referer
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • Via

getResponseHeader

获取HTTP响应头

Fetch

Fetch是一个全局函数,用来从网络上获取资源,具有两个参数 resource , init 。返回结果是Promise,请求结束时,返回 Response 对象。

resource

资源的路径 或者 Request 对象

init

method

请求方法

headers

请求头,考虑到安全问题,浏览器会禁止用户设置某些请求头

body

请求体,可以是 Blob , BufferSource , FormData URLSearchParams USVString ReadableStream 。需要注意, GET HEAD 请求不能设置 body

mode

可能的值是 cors no-cors same-origin ,具体用途不明

credentials

一个枚举值,可选的值有 omit same-origin 或者 include 。默认是 same-origin ,当发起请求时,只有同源的情况下,会带上 cookie ,跨域时不带 cookie 。设置 omit 时,任何情况下都不带 cookie 。设置 include 的情况下,同源情况下带上 cookie ,跨域时也带 cookie

// fetch跨域
var url = 'http://localhost:8090/setcookie?c=' + encodeURIComponent('random=' + Math.random());