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

Manipulating object information within a nested for loop

I have a variable called jobs in my scope, which is an array containing objects for each department along with their respective data. [ “Accounting”: { “foo” : “foo”, “bar” : "bar" }, “Delivery”: { ...

Safari's Web Audio API suffering from subpar performance and various shortcomings

For my University project, I am developing an HTML and JavaScript-based mp3 player using the Web Audio API. You can check out the progress of this project by visiting this link: While everything is running smoothly on Firefox and Chrome, Safari is posing ...

Is there a way to dynamically access BEM-style selectors using CSS modules?

For instance, I have this specific selector in my App.module.css file: .Column--active I want to access this selector from the App.js file in React using CSS modules. After importing all selectors from the CSS file as import styles from './App. ...

How can I troubleshoot the overflow-y problem in a tab modal from w3 school?

https://www.example.com/code-sample overflow: scroll; overflow-y: scroll; When I type a lot of words, they become hidden so I need to use overflow-y=scroll. Despite trying both overflow: scroll; and overflow-y: scroll;, I have been unable to achieve the ...

Using jQuery to send a POST request with a data object

Trying to figure out something. Attempting to post an object using jQuery Ajax POST, like so: var dataPostYear = { viewType:GetViewType(), viewDate:'2009/09/08', languageId:GetLanguageId() }; $.ajax({ type: "POST", url: url ...

Node.js: Steps for receiving an ArrayBuffer in a $http request

I made a request using $http.post from Angular.js to Node.js, expecting to receive an ArrayBuffer. Here is the code snippet: $http.post('/api/scholarships/load/uploaded-files', Global.user, {responseType:'arraybuffer'}).success(functi ...

Automatically activate the Focus Filterfield in the ng-multiselect-dropdown upon clicking

I've integrated the ng-multiselect-dropdown package into my Angular project using this link: https://www.npmjs.com/package/ng-multiselect-dropdown. Everything is functioning as expected, but I'm looking to automatically focus on the filter input ...

Processing ajax requests in Rails 4 using HTML format

I'm currently in the process of setting up ajax functionality for my contact form and I am currently testing to ensure that the ajax call is being made. When checking my console, I noticed that it is still being processed as HTML and I cannot seem to ...

Encountering the "potential null object" TypeScript issue when utilizing template ref data in Vue

Currently, I am trying to make modifications to the CSS rules of an <h1> element with a reference ref="header". However, I have encountered a TypeScript error that is preventing me from doing so. const header = ref<HTMLElement | null> ...

Having trouble sending Props between components within a specific route as I keep receiving undefined values

Here is the code for the initial component where I am sending props: const DeveloperCard = ({dev}) => { return ( <Link to={{pathname:`/dev/${dev._id}`, devProps:{dev:dev}}}> <Button variant="primary">Learn More</Butt ...

Retrieve dashboard configurations in AngularJS by making an $http request prior to initiating the dashboard controller

I am currently immersing myself in Angular and tackling a complex dashboard framework all built with Angular. Prior to loading the controllers, I need to fetch various dashboard settings from the server using $HTTP. These settings play a crucial role in de ...

Performing an ajax post call within the WordPress platform

Having trouble submitting a form using ajax and posting to /wp-admin/admin-ajax.php as I keep receiving response code 400. This is how I am trying to submit the form: $.ajax("/wp-admin/admin-ajax.php", { type: 'post', dataType: 'json&a ...

The div element is not adjusting its size according to the content it

Essentially, I want the #main-content div to expand so that its content fits inside without overlapping, as shown in the codepen example. I've been unsuccessful in implementing the clearfix or overflow:hidden solutions so far. It's puzzling why ...

Issue encountered while attempting to set up react-native project

Whenever I attempt to create a new react-native project using the command: npx react-native init myproject I encounter the following errors: ERESOLVE is overriding peer dependency npm gives me a warning while trying to resolve: [email protected] ...

Exploring the Functionality of Cookies in Nuxt 3 API Endpoints and Middlewares

Can cookies be utilized on the server side in Nuxt 3? For instance, I need to set a cookie in an API and then access its data in middleware: // ~/server/api/testApi.ts export default defineEventHandler(event => { /* setCookie('myCookie', ...

The ComboBox is incorrectly displaying a value after the initial load

A dropdown menu representing login types is fetched from the server and the translation of these login types needs to be done on the client side. Here is an example of the JSON data returned from the server: [ {"valueField":"activeDirectory"}, {"valu ...

Automatically close the menu in ReactJS when transitioning to a new page

I have created a nested menu, but I am facing an issue with it. Here is the structure: Parent_Menu Parent1 > Child_Menu1 > Child_Menu2 Parent2 Currently, when I click on, for example, Child_Menu1, I am redirected to the correct page ...

Processing two Array Objects can be achieved without resorting to the EVAL function

I have two objects that I need to process. obj1 contains an array of objects with formulas. obj2 holds the values needed for the calculations. I am looking for a way to process and calculate both objects in order to obtain a result where the keys present ...

Generating dynamic strings for identifiers in JSX

Can you help me figure out how to dynamically create IDs like this? <div id="track_1"></div> <div id="track_2"></div> I tried assigning the IDs from the parent component like this: export default function Compon ...

Having trouble with Vue Router view not functioning properly in my Laravel Blade page

While diving into the world of Vue.js, I encountered a perplexing issue. After successfully running ExampleComponent.vue in my admin panel and displaying its content, I attempted to import routes from an external file (new_route_list.js) and load them via ...