gpt4 book ai didi

javascript - 速率限制从 react 客户端向 API 发出的请求数

转载 作者:行者123 更新时间:2023-12-05 00:38:22 24 4
gpt4 key购买 nike

我在客户端中使用 React 和 fetch 向 Discogs API 发出请求.在此 API 中,每分钟最多 60 个请求。为了管理这个 Discogs 是在响应 header 上添加自定义值,例如“剩余请求”、“使用的请求”或“最大允许请求”,但由于 Cors,这些 header 无法读取。
所以我决定做的是为这个 API 创建一个请求包装器,我可以从这里:

  • 定义一个时间窗口(在本例中为 60 秒)。
  • 定义在此时间窗口内允许执行的最大请求数。
  • 根据限制对接收到的请求进行排队处理。
  • 能够取消请求并将它们拉出队列。

  • 我已经设法使用单例对象做了一个工作示例,其中作业排队和管理 setTimeout函数来延迟请求的调用。
    这在使用简单回调时对我有用,但我不知道 如何向 React 组件返回一个值以及如何使用 Promises 而不是回调来实现它 (拿来)。
    我也不知道 如何取消超时或来自 react 组件的 fetch 请求 .
    您可以查看 this example ,我已经简化了它。我知道这可能不是最好的方法,或者这段代码很糟糕。这就是为什么任何有关它的帮助或指导将不胜感激。

    最佳答案

    我想限制请求的数量,但也将它们搁置,直到 API 允许,所以我认为最好的选择是按 FIFO 顺序依次运行它们,它们之间有 1 秒的延迟,所以我这样做了不超过 1 分钟内 60 个请求的要求。我也在考虑让他们同时运行其中一些,但在这种情况下,一旦达到限制,等待时间可能会很长。
    然后我创造了两件事:
    'useDiscogsFetch' 钩子(Hook)

  • 将所有 API 调用作为 promise 发送到队列,而不是直接进行。
  • 它还将生成一个 UUID 来识别请求,以便在需要时取消它。为此,我使用了 uuid npm package .

  • 使用DiscogsFetch.js
    import { useEffect, useRef, useState } from 'react';
    import DiscogsQueue from '@/utils/DiscogsQueue';
    import { v4 as uuidv4 } from 'uuid';

    const useDiscogsFetch = (url, fetcher) => {

    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const requestId = useRef();

    const cancel = () => {
    DiscogsQueue.removeRequest(requestId.current);
    }

    useEffect(() => {
    requestId.current = uuidv4();
    const fetchData = async () => {
    try {
    const data = await DiscogsQueue.pushRequest(
    async () => await fetcher(url),
    requestId.current
    );
    setData(data)
    } catch (e) {
    setError(e);
    }
    };
    fetchData();
    return () => {
    cancel();
    };
    }, [url, fetcher]);

    return {
    data,
    loading: !data && !error,
    error,
    cancel,
    };

    };

    export default useDiscogsFetch;
    DiscogsQueue 单例类
  • 它将任何接收到的请求排入一个数组。
  • 请求将一次处理一个,它们之间的超时时间为 1 秒,总是从最旧的开始。
  • 它还有一个 remove 方法,它将搜索一个 id 并从数组中删除请求。

  • DiscogsQueue.js
    class DiscogsQueue {

    constructor() {
    this.queue = [];
    this.MAX_CALLS = 60;
    this.TIME_WINDOW = 1 * 60 * 1000; // min * seg * ms
    this.processing = false;
    }

    pushRequest = (promise, requestId) => {
    return new Promise((resolve, reject) => {
    // Add the promise to the queue.
    this.queue.push({
    requestId,
    promise,
    resolve,
    reject,
    });

    // If the queue is not being processed, we process it.
    if (!this.processing) {
    this.processing = true;
    setTimeout(() => {
    this.processQueue();
    }, this.TIME_WINDOW / this.MAX_CALLS);
    }
    }
    );
    };

    processQueue = () => {
    const item = this.queue.shift();
    try {
    // Pull first item in the queue and run the request.
    const data = item.promise();
    item.resolve(data);
    if (this.queue.length > 0) {
    this.processing = true;
    setTimeout(() => {
    this.processQueue();
    }, this.TIME_WINDOW / this.MAX_CALLS);
    } else {
    this.processing = false;
    }
    } catch (e) {
    item.reject(e);
    }
    };

    removeRequest = (requestId) => {
    // We delete the promise from the queue using the given id.
    this.queue.some((item, index) => {
    if (item.requestId === requestId) {
    this.queue.splice(index, 1);
    return true;
    }
    });
    }
    }

    const instance = new DiscogsQueue();
    Object.freeze(DiscogsQueue);

    export default instance;
    我不知道这是否是最好的解决方案,但它可以完成工作。

    关于javascript - 速率限制从 react 客户端向 API 发出的请求数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65850544/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com