Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMLHttpRequest 与 fetch #60

Open
wuyanqian0503 opened this issue Jul 2, 2021 · 4 comments
Open

XMLHttpRequest 与 fetch #60

wuyanqian0503 opened this issue Jul 2, 2021 · 4 comments

Comments

@wuyanqian0503
Copy link
Owner

AJAX

AJAX 是 异步的JavaScript和XML,是一种不用刷新页面就能快速将增量更新展现在页面上的技术方案,他的核心就是XMLHttpRequest

XMLHttpRequest

XHR 一个允许你在不刷新页面的情况下请求某个URL来获取数据的技术。何以使用它来与服务器交换数据,实现页面的局部更新。

@wuyanqian0503
Copy link
Owner Author

wuyanqian0503 commented Jul 2, 2021

使用XHR

基础使用

流程:

构造实例 -> open -> 注册onreadystatechange回调 -> send -> 根据status处理请求返回结果

readyState是请求状态,为3时表示正在请求,为4时表示请求完成
status是请求结果状态

let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain/service');

// request state change event
xhr.onreadystatechange = function() {
  // request completed?
  if (xhr.readyState !== 4) return;

  if (xhr.status === 200) {
    // request successful - show response
    console.log(xhr.responseText);
  } else {
    // request error
    console.log('HTTP error', xhr.status, xhr.statusText);
  }
};

// start request
xhr.send();

发起请求

open:初始化请求

xhrReq.open(method, url);
xhrReq.open(method, url, async);
xhrReq.open(method, url, async, user);
xhrReq.open(method, url, async, user, password);

根据open的第三个参数async设置请求类型,为true时表示异步,为false则表示同步调用,默认为异步。

send:发送请求

XMLHttpRequest.send();
XMLHttpRequest.send(ArrayBuffer data);
XMLHttpRequest.send(ArrayBufferView data);
XMLHttpRequest.send(Blob data);
XMLHttpRequest.send(Document data);
XMLHttpRequest.send(DOMString? data);
XMLHttpRequest.send(FormData data);

setRequestHeader:设置请求头

myReq.setRequestHeader(header, value);

timeout:设置超时时长

单位为ms,代表着一个请求在被自动终止前所消耗的毫秒数。

当数值为0时表示不做超时控制。

在IE中,超时属性可能只能在调用 open() 方法之后且在调用 send() 方法之前设置。

withCredentials:是否使用头部授权

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

此外,这个指示也会被用做响应中cookies 被忽视的标示。默认值是false。

如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials 为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials 为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。

upload:上传进度

XMLHttpRequest.upload 属性返回一个 XMLHttpRequestUpload对象,用来表示上传的进度。这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget,可以通过对其绑定事件来追踪它的进度。

事件 相应属性的信息类型
onloadstart 获取开始
onprogress 数据传输进行中
onabort 获取操作终止
onerror 获取失败
onload 获取成功
ontimeout 获取操作在用户规定的时间内未完成
onloadend 获取完成(不论成功与否)

abort:终止请求

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

var xhr = new XMLHttpRequest(),
    method = "GET",
    url = "https://developer.mozilla.org/";
xhr.open(method, url, true);

xhr.send();

if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
  xhr.abort();
}

获取响应内容

readyStatus:请求状态

XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个:

状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
3 LOADING 下载中; responseText 属性已经包含部分数据。
4 DONE 下载操作已完成。

status:请求相应中的状态码

只读属性 XMLHttpRequest.status 返回了XMLHttpRequest 响应中的数字状态码。status 的值是一个无符号短整型。在请求完成前,status的值为0。值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为0。

status码是标准的HTTP status codes。举个例子,status 200 代表一个成功的请求。如果服务器响应中没有明确指定status码,XMLHttpRequest.status 将会默认为200。

getResponsHeader、getAllResponsHeader:获取相应头

和获取请求头的方法类似

response:请求相应体

事件处理

onreadystatechange | readystatechange | readyState 属性发生变化
onloadstart | loadstart |当程序开始加载时,loadstart 事件将被触发。
onprogress | progress progress事件会在请求接收到数据的时候被周期性触发
onabort | abort|请求终止
onerror | error | 当请求遇到错误
onload | load | 请求完成的时候会触发load 事件
ontimeout | timeout|当进度由于预定时间到期而终止时,会触发timeout 事件。
onloadend | loadend |loadend事件总是在一个资源的加载进度停止之后被触发 (例如,在已经触发“error”,“abort”或“load”事件之后)

@wuyanqian0503
Copy link
Owner Author

wuyanqian0503 commented Jul 2, 2021

Fetch

基础使用

Fetch API 提供了一种全局fetch()方法,该方法位于 WorkerOrGlobalScope 这一个 mixin 中 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。

fetch方法可以接收两个参数input和options

input 参数可以是字符串,包含要获取资源的 URL。也可以是一个 Request 对象。
options 是一个可选参数。一个配置项对象,包括所有对请求的设置。可选的参数有:

  • method: 请求使用的方法,如 GET、POST。
  • headers: 请求的头信息,包含与请求关联的Headers对象。
  • body: 请求的 body 信息。注意 GET 或 HEAD 方法的请求不能包含 body 信息
  • mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
  • credentials: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项。
const url = "http://example.com/";
const options = {
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json;charset=UTF-8",
  },
  body: JSON.stringify({
    a: 10,
    b: 20,
  }),
};

fetch(url, options).then((response) => {
  console.log(response.status);
});

数据转换

fetch返回的数据需要自己做数据类型的转换。

有以下API可以用于数据类型的转换:

  • arrayBuffer()
  • blob()
  • json()
  • text()
  • formData()

中止请求

关于fetch不支持中止请求,我们可以使用AbortController,但是由于其兼容性不好,所以我们还可以使用“abortcontroller-polyfill”。

const controller = new AbortController();

const options = {
  method: "POST",
  signal: controller.signal,
  body: JSON.stringify({
    firstName: "David",
    lastName: "Pollock",
  }),
};
const promise = fetch("http://example.com/", options);

// 如果4秒钟没有响应则超时
const timeoutId = setTimeout(() => controller.abort(), 4000);

promise
  .then((response) => {
    /* 处理响应 */
  })
  .catch((error) => console.error("请求超时"));


@wuyanqian0503
Copy link
Owner Author

另外 window.fetch 函数只是 Fetch API 提供的众多接口中的一个,还有很多有用的对象:

window.Headers
window.Response
window.Request
……

@wuyanqian0503
Copy link
Owner Author

fetch和XMLHttpRequest的区别

  • fetch对于Http错误的状态码也会进行resolve,只有在网络异常或者请求发送失败的情况下,才会reject
  • fetch不支持progress事件
  • fetch的浏览器兼容性更低一些
  • fetch不支持中止请求,部分浏览器支持AbortController,也可以利用setTimeout和Promise.race来手动封装
  • fetch是基于Promise的,可以直接链式调用
  • fetch的使用语法不同
  • fetch默认不携带cookie,需要设置credentials才可以携带

fetch和Axios的区别

  • fetch对于Http错误的状态码也会进行resolve,只有在网络异常或者请求发送失败的情况下,才会reject
  • fetch不支持progress事件
  • fetch是浏览器原生支持的
  • fetch不支持拦截器
  • fetch不支持中止
  • post请求中fetch使用body携带数据,而axios使用data
  • Axios会自动帮你做响应数据的转换,而fetch需要自己调用API进行转换

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant