下一代Ajax技术 — Fetch的学习与使用

一、初识fetch

在这里插入图片描述

Fetch被称为下一代Ajax技术,采用Promise方式来处理数据。是一种简洁明了的API,比XMLHttpRequest更加简单易用。

XMLHttpRequest

我们先来看看使用纯XMLhttpRequest来实现一次简单ajax请求的代码:

//获取XMLHttpRequest实例对象
const xhr = new XMLHttpRequest();
//初始请求
xhr.open("get", "https://jsonplaceholder.typicode.com/users");
//发送数据
xhr.send();
//设置xhr请求状态修改回调
xhr.onreadystatechange = function () {
    
    
    //如果请求状态已完成时
    if (xhr.readyState === 4) {
    
    
        //如果响应状态码大于等于200并且小于300时
        if (xhr.status >= 200 && xhr.status < 300) {
    
    
            //请求成功
            console.log(JSON.parse(xhr.response));
        } else {
    
    
            //请求失败
            console.log("请求失败!");
        }
    }
};

请不要把XMLHttpRequest和Ajax弄混了,Ajax只是一种思想或者技术,而XMLHttpRequest是一个原生对象,可以使用他实现Ajax。

fetch

Fetch 是一个现代的概念,等同于 XMLHttpRequest。它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。
注意,Fetch是JavaScript提供的原生API,所以是可以直接使用的,我们同样使用fetch来请求上一个例子的接口:

fetch("https://jsonplaceholder.typicode.com/users")
  .then((res) => res.json())
  .then((data) => console.log(data));

可以看到,fetch是返回的Promise实例,可以直接进行链式调用,代码更加简单易懂,也可以使用async和await。

Axios

Axios中文官网
其实可以发现,fetch和axios的使用方法十分相似,因为Axios的浏览器端其实就是XMLHttpRequest结合Promise的封装结果。
因此,fetch其实是可以直接代替Axios来进行浏览器端发起请求的,直接用原生的!
在这里插入图片描述

二、fetch配置

既然说fetch可以代替axios,那么fetch肯定和axios一样,可以配置许多选项,来完成不同的请求,例如获取数据、修改数据、上传文件等等……

配置

Promise<Response> fetch(input[, init]);

第一个参数input是定义要获取的资源。这可能是:

  • 一个 USVString 字符串,包含要获取资源的 URL。一些浏览器会接受 blob: 和 data: 作为 schemes. 一个
  • Request 对象。 fetch方法还可以接受第二个参数(可选),作为配置对象,定制发出的 HTTP 请求。

第二个参数(init)是可选参数对象:

fetch(url, {
    
    
    method: "GET",//请求方法 默认get
    headers: {
    
    //配置请求头
        "Content-Type": "text/plain;charset=UTF-8"
    },
    body: data,//请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
    referrer: "about:client",// 一个 USVString 可以是 no-referrer、client 或一个 URL。默认是 client。
    referrerPolicy: "no-referrer-when-downgrade",//指定了 HTTP 头部 referer 字段的值。可能为以下值之一:no-referrer、 no-referrer-when-downgrade、origin、origin-when-cross-origin、 unsafe-url。
    mode: "cors",//请求的模式,如 cors、no-cors 或者 same-origin。
    credentials: "same-origin",// 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie,必须提供这个选项。
    cache: "default",// 请求的 cache 模式:default、 no-store、 reload 、 no-cache、 force-cache 或者 only-if-cached。
    redirect: "follow",//可用的 redirect 模式:follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误),或者 manual (手动处理重定向)。在 Chrome 中默认使用 follow(Chrome 47 之前的默认值是 manual)
    integrity: "",//包括请求的 subresource integrity 值(例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
    keepalive: false,//而这个参数是在说,即使页面已经不在了,这个请求依然需要完成,因此浏览器会延长它的生存期。
    signal: undefined//配合AbortController完成请求中断操作
});

三、常用对象及方法

fetch()采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象),使得编写的代码更加合理,逻辑也更加清晰。

Request

Request MDN文档
前面说到fetch的第一个参数可以是一个Request对象。

var myRequest = new Request(input[, init]);

与fetch()的参数好像差不多。

实例方法

arrayBuffer()

Request 接口的 arrayBuffer() 方法读取请求体并将其作为一个 promise 返回,该 promise 将兑现一个 ArrayBuffer

const myArray = new Uint8Array(10);

const request = new Request('/myEndpoint', {
    
    
  method: 'POST',
  body: myArray
});

request.arrayBuffer().then(function(buffer) {
    
    
  // do something with the buffer sent in the request
});

blob()

Request 接口的 blob() 方法读取请求体并将其作为 promise 返回,该 promise 将兑现一个 Blob。

const obj = {
    
    hello: 'world'};
const myBlob = new Blob([JSON.stringify(obj, null, 2)], {
    
    type : 'application/json'});

const request = new Request('/myEndpoint', {
    
    
  method: 'POST',
  body: myBlob
 });

request.blob().then(function(myBlob) {
    
    
  // do something with the blob sent in the request
});

clone()

Request 接口中的clone() 方法可以创建一个当前Request 对象的副本。

formData

Request 接口的 formData() 方法读取请求体并将其作为 promise 返回,该 promise 将兑现一个 FormData 对象。

const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

const request = new Request('/myEndpoint', {
    
    
  method: 'POST',
  body: formData
});

request.formData().then(function(data) {
    
    
  // do something with the formdata sent in the request
});

json()

Request 接口的 json() 方法读取请求体并将其作为一个 promise 返回,该 promise 将兑现一个由响应体的文本解析得到的 JSON。

注意,尽管方法被命名为 json(),结果并不是 JSON,而是将输入作为 JSON 解析,以生成一个 JavaScript 对象

返回一个将兑现一个 JavaScript 对象的 Promise。这个对象可能是任何可以用 JSON 表示的东西——一个对象、一个数组、一个字符串、一个数值……

const obj = {
    
    hello: 'world'};

const request = new Request('/myEndpoint', {
    
    
  method: 'POST',
  body: JSON.stringify(obj)
 });

request.json().then(function(data) {
    
    
  // do something with the data sent in the request
});

text()

Request 接口的 text() 方法读取请求体并且将其作为一个 promise 返回,该 promise 将兑现一个 String。响应总是使用 UTF-8 解码。

Response

你可以使用 Response.Response() 构造函数来创建一个 Response 对象,但通常更可能遇到的情况是,其他的 API 操作返回了一个 Response 对象。

let r = new Response(); 
console.log(r); 
// Response { 
// body: (...) 
// bodyUsed: false //包含了一个布尔值 (en-US)来标示该 Response 是否读取过 Body。
// headers: Headers {} //包含此 Response 所关联的 Headers 对象。
// ok: true //包含了一个布尔值,标示该 Response 成功(HTTP 状态码的范围在 200-299)。
// redirected: false //表示该 Response 是否来自一个重定向,如果是的话,它的 URL 列表将会有多个条目。
// status: 200 //包含 Response 的状态码(例如 200 表示成功)。
// statusText: "OK" //包含了与该 Response 状态码一致的状态信息(例如,OK 对应 200)。
// type: "default" //包含 Response 的类型(例如,basic、cors)。
// url: "" //包含 Response 的 URL。
// } 

静态方法

error()

Response 接口的 error() 方法返回一个包含网络错误相关信息的新 Response 对象。

redirect()

Response 接口的 redirect() 方法返回一个可以重定向到指定 URL 的 Response 。

var response = Response.redirect(url, status);

实例方法

arrayBuffer

Response上的方法 arrayBuffer() 接受一个 Response 流,并等待其读取完成。它返回一个 promise 实例,并 resolve 一个 ArrayBuffer 对象。

response.arrayBuffer().then(function(buffer) {
    
    
  // do something with buffer
)};

blob

Response mixin 的 **blob()**方法使用一个 Response 流,并将其读取完成。它返回一个使用Blob解决的 promise。

response.blob().then(function(myBlob) {
    
    
  // do something with myBlob
});

clone

Response 接口的 clone() 方法创建一个响应对象的克隆,这个对象在所有方面都是相同的,但是储存在不同的变量中。
如果响应体已经被使用,clone() 抛出 TypeError。事实上,clone() 存在的主要原因是允许 body 对象可以使用多次(当它们是一次性使用时)。

const image1 = document.querySelector('.img1');
const image2 = document.querySelector('.img2');

const myRequest = new Request('flowers.jpg');

fetch(myRequest).then((response) => {
    
    
  const response2 = response.clone();

  response.blob().then((myBlob) => {
    
    
    const objectURL = URL.createObjectURL(myBlob);
    image1.src = objectURL;
  });

  response2.blob().then((myBlob) => {
    
    
    const objectURL = URL.createObjectURL(myBlob);
    image2.src = objectURL;
  });
});

formData

Response 对象中的formData() 方法将 Response 对象中的所承载的数据流读取并封装成为一个对象,该方法将返回一个 Promise 对象,该对象将产生一个FormData 对象。

response.formData()
.then(function(formdata) {
    
    
  // do something with your formdata
});

json

Response mixin 的 json() 方法接收一个 Response 流,并将其读取完成。它返回一个 Promise,Promise 的解析 resolve 结果是将文本体解析为 JSON。

response.json().then(data => {
    
    
  // do something with your data
});

返回一个被解析为 JSON 格式的 promise 对象,这可以是任何可以由 JSON 表示的东西 - 一个 object,一个 array,一个 string,一个 number…

text

Response mixin 的 text() 方法提供了一个可供读取的“返回流”(Response stream),并将它读取完。它返回一个包含 USVString 对象(也就是文本)的 Promise 对象,返回结果的编码永远是 UTF-8。

response.text().then(function (text) {
    
    
  // do something with the text response
});

Headers

Fetch API 的 Headers 接口允许您对 HTTP 请求和响应头执行各种操作。这些操作包括检索,设置,添加和删除。一个 Headers 对象具有关联的头列表,它最初为空,由零个或多个键值对组成。

构造函数Headers()

var myHeaders = new Headers(init);

init 参数可选:通过一个包含任意 HTTP headers 的对象来预设你的 Headers. 可以是一个ByteString 对象; 或者是一个已存在的 Headers 对象。

append()

在一个Headers对象内部,Headers接口的 append() 方法可以追加一个新值到已存在的 headers 上,或者新增一个原本不存在的 header。

myHeaders.append(name,value);

delete()

delete() 方法可以从 Headers 对象中删除指定 header.
下列原因将会导致该方法抛出一个TypeError:

  1. header 名在 HTTP header 中是不存在的。
  2. header 被锁定了。
myHeaders.delete(name);

entries()

Headers.entries() 以 迭代器 的形式返回 Headers 对象中所有的键值对。

// Create a test Headers object
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/xml');
myHeaders.append('Vary', 'Accept-Language');

// Display the key/value pairs
for (var pair of myHeaders.entries()) {
    
    
   console.log(pair[0]+ ': '+ pair[1]);
}

forEach()

和遍历数组的forEach方法类似。

// Create a new test Headers object
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "This is a demo cookie");
myHeaders.append("compression", "gzip");

// Display the key/value pairs
myHeaders.forEach((value, key) => {
    
    
  console.log(`${
      
      key} ==> ${
      
      value}`);
})

返回

compression ==> gzip
content-type ==> application/json
cookie ==> This is a demo cookie

get()

获取指定headers属性的值。

const myHeaders = new Headers(); // Currently empty
myHeaders.get('Not-Set'); // Returns null

has()

Headers 接口的 **has()**方法返回一个布尔值来声明一个 Headers对象 是否包含特定的头信息。

myHeaders.append('Content-Type', 'image/jpeg');
myHeaders.has('Content-Type'); // Returns true
myHeaders.has('Accept-Encoding'); // Returns false

keys()

eaders.keys() 方法返回一个 headers(Object) 对象所有 key 组成的迭代器,通过迭代器可以遍历 headers 这个对象,返回的迭代器中的元素 key 都是字符串。

// 创建一个 Headers 对象
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/xml');
myHeaders.append('Vary', 'Accept-Language');

// 显示 Headers 中所有的 key
for(var key of myHeaders.keys()) {
    
    
   console.log(key);
}

set()

Headers.set 和 append() 两者之间的不同之处在于当指定 header 是已经存在的并且允许接收多个值时,Headers.set会重写此值为新值,而append()会追加到值序列的尾部

myHeaders.set('Accept-Encoding', 'deflate');
myHeaders.set('Accept-Encoding', 'gzip');
myHeaders.get('Accept-Encoding'); // Returns 'gzip'

values()

Headers.values() 方法返回一个可迭代数值,通过这个数值可以遍历 Headers 中键值对的 value 值。返回的 value 都是 ByteString 对象。

// Create a test Headers object
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/xml');
myHeaders.append('Vary', 'Accept-Language');

// Display the values
for (var value of myHeaders.values()) {
    
    
   console.log(value);
}
text/xml
Accept-Language

以上内容全部参考于mdn web docs - Fetch API

猜你喜欢

转载自blog.csdn.net/ZHANGYANG_1109/article/details/127996511