如何取消 HTTP 请求

120 阅读1分钟

创建react项目

react官网推荐创建 react 项目的方式改变了,除了 next.js 还有使用React Router(V7) 这种方式。

npx create-react-router@latest

然后进入项目安装相关依赖

npm i -D mockjs @types/mockjs vite-plugin-mock
npm i -S axios

目录结构:

image.png

添加对mockjs 的支持

vite.config.js配置

// vite.config.ts

import { reactRouter } from "@react-router/dev/vite";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { viteMockServe } from "vite-plugin-mock";// 引入

const isDev = process.env.NODE_ENV === "development";// 开发环境使用

export default defineConfig({
  plugins: [
    tailwindcss(),
    reactRouter(),
    tsconfigPaths(),
    isDev && // 配置
      viteMockServe({
        mockPath: "mocks",
        watchFiles: true,
        enable: true,
      }),
  ],
});

mockjs API 配置

image.png

// mocks/index.ts
import Mock from "mockjs";

export default [
  {
    url: "/mock/users",
    method: "GET",
    timeout: 3000,
    response: () => {
      const res = Mock.mock({
        "list|5": [
          {
            id: "@guid",
            name: "@cname",
            email: "@email",
            address: "@county(true)",
          },
        ],
      });
      return res.list;
    },
  },
];

取消请求的逻辑

// app/routes/home.tsx

import {
  useRef,
  useEffect,
  useActionState,
  startTransition,
  useState,
} from "react";
import type { Route } from "./+types/home";

export function meta({}: Route.MetaArgs) {
  return [
    { title: "取消 http 请求" },
    { name: "description", content: "如何取消 http 请求" },
  ];
}

export default function Home() {
  const controllerRef = useRef<any>(null);
  const [data, fetchUsers, isPending] = useActionState(async () => {
    try {
      controllerRef.current = new AbortController();
      const res = await fetch("/mock/users", {
        signal: controllerRef.current.signal,
      });
      const d = await res.json();
      console.log(d);
      return d;
    } catch (error: any) {
      if (error.name === "AbortError") {
        console.log("Fetch aborted");
      } else {
        console.error("Fetch error:", error);
      }
    }
  }, null);

  return (
    <div className="">
      <button
        className="w-30 cursor-pointer hover:bg-amber-600 rounded-2xl border-amber-900 border-4"
        disabled={isPending}
        onClick={() => {
          startTransition(() => {
            fetchUsers();
          });
        }}
      >
        Fetch Users
      </button>
      <button
        className="w-40 ml-2 cursor-pointer hover:bg-amber-600 rounded-2xl border-amber-900 border-4"
        onClick={() => {
          controllerRef.current?.abort();
        }}
      >
        Cancel Fetch Users
      </button>
      <ul>
        {data?.map((d: any) => (
          <li key={d.email}>{d.name}</li>
        ))}
      </ul>
    </div>
  );
}

结果如下:

image.png