Leon's blog Leon's blog
首页
前端
场景
技术
更多
关于
收藏
索引
GitHub (opens new window)

Leon Yu

做一个有个性的开发者~
首页
前端
场景
技术
更多
关于
收藏
索引
GitHub (opens new window)
  • 场景
  • ResizeObserver防抖优化性能
  • useAbortableRequest
    • requestAnimation与滚动
    • 支持promise的并发
    • 单点登录场景与理解
    • 前端路由
    • 场景
    leon yu
    2024-06-15
    目录

    useAbortableRequest

    # web API 之 AbortController

    AbortController: abort()方法 (opens new window)

    AbortController 接口的 abort() 方法会在一个异步操作完成之前中止它。它能够中止 fetch 请求、各种响应主体或者流的消耗。

    const controller = new AbortController();
    const signal = controller.signal;
    
    const url = "video.mp4";
    const downloadBtn = document.querySelector(".download");
    const abortBtn = document.querySelector(".abort");
    
    downloadBtn.addEventListener("click", fetchVideo);
    
    abortBtn.addEventListener("click", () => {
      controller.abort();
      console.log("Download aborted");
    });
    
    function fetchVideo() {
      fetch(url, { signal })
        .then((response) => {
          console.log("Download complete", response);
        })
        .catch((err) => {
          console.error(`Download error: ${err.message}`);
        });
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    # 工作需求

    在工作中,ant design 表格会在查询后发起请求,有时候用户请求较快,会造成过多的重复请求,会对服务器造成较大的压力,于是就有了希望能在上一次请求没有完成,但是已经发起下一次请求的同时,能够取消上一次的请求。

    # 代码实现

    import { useState, useCallback } from 'react';
    
    /**
     * 使用umi.js和AbortController实现的防止重复请求的React Hook
     * @param {Function} requestFunction - 请求函数,该函数需要返回一个Promise
     * @returns {Array} - 返回一个数组,包含请求函数和当前请求状态
     */
    function useAbortableRequest(requestFunction) {
      // 保存当前的AbortController实例
      const [controller, setController] = useState(null);
      // 请求状态
      const [loading, setLoading] = useState(false);
    
      const sendRequest = useCallback(async (...args) => {
        // 如果存在上一个请求,先取消上一个请求
        if (controller) {
          controller.abort();
        }
        // 创建新的AbortController实例
        const newController = new AbortController();
        setController(newController);
        setLoading(true);
    
        try {
          // 调用请求函数,传入signal
          const response = await requestFunction(...args, { signal: newController.signal });
          setLoading(false);
          return response;
        } catch (error) {
          // 如果请求被取消,不更新loading状态
          if (error.name !== 'AbortError') {
            setLoading(false);
          }
          throw error;
        }
      }, [controller, requestFunction]);
    
      return [sendRequest, loading];
    }
    
    export default useAbortableRequest;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    使用示例:

    import React, { useEffect } from 'react';
    import { useAbortableRequest } from './useAbortableRequest';
    import { request } from 'umi';
    
    // 模拟请求函数
    const fetchData = (params, { signal }) => {
      return request('/api/data', { method: 'GET', params, signal });
    };
    
    const MyComponent = () => {
      const [fetchDataWithAbort, loading] = useAbortableRequest(fetchData);
    
      useEffect(() => {
        fetchDataWithAbort({ query: 'example' })
          .then(response => {
            console.log(response);
          })
          .catch(error => {
            if (error.name !== 'AbortError') {
              console.error(error);
            }
          });
    
        // 组件卸载时取消请求
        return () => {
          fetchDataWithAbort();
        };
      }, [fetchDataWithAbort]);
    
      return <div>{loading ? '加载中...' : '加载完成'}</div>;
    };
    
    export default MyComponent;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

    这个Hook useAbortableRequest 接收一个请求函数作为参数,返回一个可以被调用的请求函数和当前请求的加载状态。请求函数内部使用AbortController来取消上一个未完成的请求,以防止重复请求。

    最近更新~: 2024/08/19, 01:05:55
    ResizeObserver防抖优化性能
    requestAnimation与滚动

    ← ResizeObserver防抖优化性能 requestAnimation与滚动→

    最近更新
    01
    应用层
    01-11
    02
    计算机网络和因特网
    12-22
    03
    关于
    12-22
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 主题来自 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式