Is there a method to delay HTTP requests until the number of pending requests drops below a certain threshold (N)?

I'm in the midst of a project that involves allowing users to upload multiple files simultaneously. However, sending out numerous requests all at once can overwhelm the server and trigger a 429 (Too Many Requests) error for those requests.

Is there a way to prevent a request from being sent out (without affecting the UI) if there are already a certain number of pending requests?

Below is a simplified code snippet to demonstrate what I am currently implementing:

filesToUpload.forEach(function(file) {
    // This function converts the file to base64, prepares the payload,
    // makes a POST request, and returns a promise
    upload(file, successCallback, errorCallback);
}

Answer №1

In my opinion, the most effective method would be to wrap the HTTP request in an asynchronous function.

Utilizing the async and await keywords allows for promise-based asynchronous behavior

When using the await keyword, the code will pause until the post request is complete before proceeding with sending another request to the server where the files are stored.

To learn more about the syntax and usage of async and await, you can visit this resource.

Answer №2

One way to approach this is by utilizing recursion in a sequential manner. However, it's important to make sure the code can handle potential errors.

(function uploadFilesSequentially(files, successCallback, errorCallback){
    if(files.length){
        upload(files.shift(), (...args) => {
            successCallback(...args);
            uploadFilesSequentially(files, successCallback, errorCallback)
        }, errorCallback);
    }
})(filesToUpload, successCallback, errorCallback);

Answer №3

To handle your situation effectively, consider implementing a loop and a queue.

const UPLOAD_QUEUE = [];
let progress_queue = [];
const MAX_UPLOADS = 5;

throttledUpload();

function throttledUpload() {
    const max = MAX_UPLOADS - progress_queue.length;
    for(let i = 0; i < UPLOAD_QUEUE.length; i++){
        if(i > max) break;
        uploadFile(UPLOAD_QUEUE[i], i);
    }
    progress_queue = progress_queue.concat(UPLOAD_QUEUE.splice(0, max));
}

async function uploadFile(file, idx) {
    try {
        await upload(file, successCallback, errorCallback);
        throttledUpload();
    } catch (err) {
        UPLOAD_QUEUE.push(file);
    } finally {
        progress_queue.splice(idx, 1);
        throttledUpload();
    }
}

Answer №4

This particular method utilizes traditional callbacks: it allows for a maximum of K concurrent uploads, waiting if necessary. The upload function can be revamped to use Promises.

var filesToUpload = [
  "file1.txt",
  "file2.txt",
  "file3.txt",
  "file4.txt",
  "file5.txt",
  "file6.txt",
  "file7.txt",
  "file8.txt",
]

function upload(filename, callback) {
  // This function converts the specified file to base64,
  // prepares the payload, sends a POST request, and returns a promise
  setTimeout(function() {
    console.log("<!-- uploaded " + filename);
    typeof callback === 'function' && callback()
  }, Math.random() * 1000 + 500)
}


function start_sequence(filesToUpload, maxK, callback) {
  var K = maxK;

  function do_loop(filesToUpload, callback) {

    if (!filesToUpload.length) {
      if (K == maxK) {
        // End the loop
        typeof callback === 'function' && callback();
      }
      return;
    }

    // Upload the first K files now
    while (K > 0) {
      K--
      var first = filesToUpload.shift();
      console.log("--> sending " + first);
      upload(first, function() {
        K++;
        do_loop(filesToUpload, callback)
      });
    }
  }

  // Start the loop
  do_loop(filesToUpload, callback);

}


start_sequence(filesToUpload, 3, function() {
  console.log("all done!")
});
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Selecting elements by their name using vanilla JavaScript

I am facing an issue where I have to assign a value to a checkbox based on certain variables. The challenge lies in the naming convention used in the HTML I am working with: <input id="jc_1" type="checkbox" name="jc[1]"> <input id="jc_2" type="c ...

Changing the order of element names depending on their location within the parent element using jQuery

<div class="content"> <div> <input type="text" name="newname[name]0"/> <div> <input type="text" name="newname[utility]0"/> <div> <textarea name="newname[text]0 ...

Is it possible to add items to a JS object that isn't an array?

Here is an example of the object I am working with: { "_id": "DEADBEEF", "_rev": "2-FEEDME", "name": "Jimmy Strawson", "link": "placeholder.txt", "entries": { "Foo": 0 } } To access this data in my JavaScript code, I use a $.getJSON call. ...

Using JSON to pass a dynamic array to Morris Chart

My task involves creating a graph using Morris Charts with a dynamic rectangular array. The array consists of a variable number of columns and looks like this: To achieve this, I attempted to pass the data to Morris Charts using JSON. Below is a snippet o ...

When attempting to make a GET request, Express/Mongoose is returning a null array

I am having trouble retrieving the list of books from my database. Even though I have successfully inserted the data into Mongoose Compass, when I try to fetch it, all I get is an empty array. //Model File import mongoose from "mongoose"; cons ...

Adjusting the width of a nested iframe within two div containers

I am trying to dynamically change the width of a structure using JavaScript. Here is the current setup: <div id="HTMLGroupBox742928" class="HTMLGroupBox" style="width:1366px"> <div style="width:800px;"> <iframe id="notReliable_C ...

When emitting events in Vue.js, they do not automatically bubble up to higher level parent or grandparent elements

I'm trying to dispatch a custom event that will bubble up from the grandchild element through the child element to the parent element, but for some reason it's not working. Even manually triggering the event on either the parent or child element ...

The basket_add function in basket.views did not generate an HttpResponse object, but instead returned a None value

Previously, I had success adding the price to my product. However, when I tried to add the quantity, something went wrong. Despite watching it over and over again, I couldn't figure out the issue. Any help would be greatly appreciated. This is the er ...

Is there an issue with loading CSS and JavaScript in mobile view on a website built with CodeIgniter?

My experience with codeigniter has been great so far, but I encountered an issue when trying to view my work on different devices. Here is the problem: Web: Broswer View | Browser (Responsive Design View) Mobile: Screenshot 1 | Screenshot 2 _htaccess: ...

Explore the wonders of generating number permutations using JavaScript recursion!

After providing the input of 85 to this function, I noticed that it only returns 85. I am confused as to why it is not recursively calling itself again with 5 as the first number. console.log(PermutationStep(85)); function PermutationStep(num) { var ...

The success variable is not functioning properly in the Statamic Antlers template when attempting to submit a form via AJAX

I have encountered an issue while using Statamic Form and Antlers template with AJAX to submit a form. The success variable does not seem to be functioning correctly, preventing me from updating the text to indicate that the form has been submitted. {{ for ...

What causes errors in jQuery ajax jsonp requests?

"fnServerData": function( sUrl, aoData, fnCallback, oSettings ) { oSettings.jqXHR = $.ajax( { "url": sUrl, "data": aoData, "success": fnCallback, "error":function(msg){ ...

Utilizing AngularJS: Employing the $q Promise Feature to Await Data Readiness in this Scenario

I am currently facing an issue with my Controller and Factory. The Controller initiates an API call in the Factory, but I am struggling to make it wait for the data to be gathered before proceeding. This is where I believe implementing something like $q mi ...

Determine the position and quantity of elements in jQuery by comparing their IDs with the current page or element

Looking to retrieve the n (zero based) position of an element by matching the page and element ID... Let's use an example (Assume the current page ID is 488); <ul id="work-grid"> <li id="item-486" class="work-item"><!--/content--& ...

Error message notifying user that an index is not defined in an ajax

This may appear to be a repetitive question, but I assure you it's not. Despite my efforts on Google, the bug persists. The problem lies in the php script's inability to set the $_POST array to the value passed by the ajax post request. I have a ...

Incorporate an additional form into every view

If I have multiple views with multiple controllers, my goal is to include the same login form in each one of them. The index page serves as the container for all the views and features a link to toggle the modal login window. INDEX.HTML <html> . ...

How can I properly integrate multer with Node and Express in this situation?

I've been working on setting up a route for uploading photos, but after making some changes, it has stopped functioning and I'm not sure how to fix it. const multer = require('multer'); // MULTER STORAGE const multerStorage = multer.di ...

"Utilizing the usePrevious hook in React: A step-by-step

After referencing the React documentation, it seems like I may not be using this code correctly. import { useEffect, useRef } from 'react'; export default function usePreviousState(state) { const ref = useRef(); useEffect(() => { ref ...

Refreshing web pages using AJAX

I currently have an application that includes a search feature where users can look up items in the database. The search functionality is working well with AJAX, but I'm now looking to incorporate this AJAX functionality into my pagination system. Spe ...

Tips for ensuring elements within a modal receive immediate focus when opened in Angular 2

I am relatively new to Angular JS and I am encountering some challenges with implementing a directive in Angular 2 that can manage focusing on the modal when it is opened by clicking a button. There have been similar queries in the past, with solutions pr ...