传统Ajax、axios和fetch如何中断请求

122 阅读1分钟

一、简单请求和复杂请求

一个简单请求需满足:

1、请求方法为: HEAD、GET、POST

2、不得人为设置除了: Accept、Accept-Language、Content-Language、Content-Type,之外的请求头;且 Content-Type 只能为 application/x-www-form-urlencoded、multipart/form-data、text/plain之一

非简单请求均为复杂请求;

当请求跨域且是一个复杂请求时,会先发送一个OPTIONS预检请求;需要尽量减少预检请求的发送次数,达到性能优化的目的,例如设置:Access-Control-Max-Age。

二、Ajax

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button onclick="handleAbort()">中断请求</button>
    <script>
      // 1、创建xhr对象
      const xhr = new XMLHttpRequest();
      // 2、配置xhr对象
      xhr.open(
        "GET",
        "https://img1.baidu.com/it/u=1877910717,1572929573&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
      );
      // 3、定义数据接收回调
      // xhr.onload也行,load执行时readyState为4
      xhr.onreadystatechange = () => {
        if (xhr.readyState !== 4) {
          return;
        }

        if (/^2(\d){2}$/.test(xhr.status)) {
          console.log("请求成功");
        } else {
          console.error("请求失败");
        }
      };
      // 4、发起请求
      xhr.send();

      // 在请求未完成时,可以中止,中止后xhr.status为0
      const handleAbort = () => {
        // 请求中止回调
        xhr.onabort = () => {
          console.log('请求中止');
        };

        xhr.abort();
      };
    </script>
  </body>
</html>

三、axios

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style></style>
  </head>
  <body>
    <button id="abortBtn">中断请求</button>

    <script type="module">
      import axios from "./node_modules/axios/dist/esm/axios.min.js";

      // 通过该对象来中断请求,CancelToken已被弃用
      const controller = new AbortController();

      axios
        .get(
          "https://img1.baidu.com/it/u=1877910717,1572929573&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
          {
            signal: controller.signal,
          }
        )
        .then((res) => {
          console.log("请求成功");
        })
        .catch((e) => {
          if (e.code === "ERR_CANCELED") {
            console.log("请求取消");
          } else {
            console.log("请求失败");
          }
        });

      // 在type=module模式下,需使用addEventListener绑定点击事件
      // 具体查看:https://blog.csdn.net/zdyah/article/details/120717382
      document.getElementById("abortBtn").addEventListener("click", () => {
        controller.abort();
      });
    </script>
  </body>
</html>

四、fetch

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style></style>
  </head>
  <body>
    <button onclick="handleAbort()">中断请求</button>

    <script>
      const controller = new AbortController();

      fetch(
        "https://img1.baidu.com/it/u=1877910717,1572929573&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
        {
          signal: controller.signal,
        }
      )
        .then((res) => {
          console.log("请求成功");
        })
        .catch((e) => {
          if (e.name === "AbortError") {
            console.log("请求取消");
          } else {
            console.log("请求失败");
          }
        });

      const handleAbort = () => {
        controller.abort();
      };
    </script>
  </body>
</html>