Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
110 views
in Technique[技术] by (71.8m points)

javascript - Limit the number of request made from the client to an specific API

I'm using React and fetch in the client to make requests to the Discogs API. In this API, there's a limit of max 60 request per minute. For managing this Discogs is adding custom values like "remaining requests", "used requests" or "maximum allowed requests", on the response headers but due to cors those headers cannot be readed.

So what I decided to do is to create a request wrapper for this API, from where I could:

  • Define a time window (in this case 60 secs).
  • Define the max requests allowed to do in this time window.
  • Queue the received requests to be processed according to the limits.
  • Be able to cancel the requests and pull them out of the queue.

I've managed to do a working example using a singleton Object where the jobs are queued and managed with setTimeout function to delay the call of the request.

This works for me when using simple callbacks, but I don't know how to return a value to the React component and how to implement it with Promises instead of callbacks (fetch).

I also don't know how to cancel the timeout or the fetch request from the react component.

You can check this example, where I've simplified it. I know that maybe that's not the best way to do it or maybe this code is shit. That's why any help or guidance on it would be very much appreciated.

question from:https://stackoverflow.com/questions/65850544/limit-the-number-of-request-made-from-the-client-to-an-specific-api

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You do not need a setTimout (so you don't need to cancel the setTimeout), and you do not need to cancel the fetch.

To use a value inside a React component, you have to use a React state. React would not know about changes to some outside object (like your singleton object).

You can store the timestamps of the last n requests, and if the first one is older than the time period, you can remove it and make a new request.

const useLimitedRequests = function(){
    const limit = 5;
    const timePeriod = 6 * 1000;
    const [ requests, setRequests ] = useState([]);

    return [
        requests,
        function(){
            const now = Date.now();

            if( requests.length > 0 && (requests[0] < now - timePeriod) ){
                setRequests( requests.slice(1) );
            }

            if( requests.length < limit ){
                setRequests([ ...requests, now ]);
                return now;
            }

            return 0;
        }
    ];
};

export const LimitedRequests = (props)=>{
    const [ requests, addRequest ] = useLimitedRequests();
    return (<>

        <button onClick={ ()=>{
            if( addRequest() > 0 ){
                console.log('ok, do fetch again');
            } else {
                console.log('no no, you have to wait');
            }
        }}>
            fetch again
        </button>

        { requests.map(function( req ){
            return <div key={ req }>{ req }</div>;
        })}
    </>);
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...