• 下一代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("请求失败!");
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    请不要把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));
    
    • 1
    • 2
    • 3

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

    Axios

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

    二、fetch配置

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

    配置

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

    第一个参数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完成请求中断操作
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    三、常用对象及方法

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

    Request

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

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

    与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
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    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
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    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
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    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
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    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。
    // } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    静态方法

    error()

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

    redirect()

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

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

    实例方法

    arrayBuffer

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

    response.arrayBuffer().then(function(buffer) {
      // do something with buffer
    )};
    
    • 1
    • 2
    • 3
    blob

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

    response.blob().then(function(myBlob) {
      // do something with myBlob
    });
    
    • 1
    • 2
    • 3
    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;
      });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    formData

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

    response.formData()
    .then(function(formdata) {
      // do something with your formdata
    });
    
    • 1
    • 2
    • 3
    • 4
    json

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

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

    返回一个被解析为 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
    });
    
    • 1
    • 2
    • 3

    Headers

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

    构造函数Headers()

    var myHeaders = new Headers(init);
    
    • 1

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

    append()

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

    myHeaders.append(name,value);
    
    • 1

    delete()

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

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

    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]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    返回

    compression ==> gzip
    content-type ==> application/json
    cookie ==> This is a demo cookie
    
    • 1
    • 2
    • 3

    get()

    获取指定headers属性的值。

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

    has()

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

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

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    set()

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

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

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    text/xml
    Accept-Language
    
    • 1
    • 2

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

  • 相关阅读:
    苏轼在密州的四首千古名作
    【C语言】 函数
    SSM框架--Spring介绍及入门
    【JMeter】定时器分类以及场景介绍
    浏览器中子域名之间共享cookie
    数据分析必备:6大步骤+5大类型+2大分析方法
    一款好的软件,软件测试必不可少...
    Three.js使用shader根据高度渐变染色
    vtkjs中Sample Distance功能
    蓝博图《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著 ​​​
  • 原文地址:https://blog.csdn.net/ZHANGYANG_1109/article/details/127996511