Search code examples
jqueryapipromisesettimeoutapiary

Need to send request to API every 2 seconds after promise is resolved, runs in finite loop


I will try my best to explain my problem.

I have javascript Promise, 2 API and setTimeout in action.

    $.each(result[1], function(i, coin) {

        var coincalcClass = new coincalculationClass();

        // this method returns a promise.
        var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);

        setTimeout(function()  {

        highforMonth.then(function (value) {

            var market_name = coin.mktName;
            var bestPrice = value['1'];

                addAlert('BTRX', market_name, bestPrice);
        }
        )
       }, 1000);//time in milliseconds

    });

so, in the code, First I have a json value, (50 values) and I am going through each of them. I am making some calulations. I call getHighLowForSpecificDays() method which returns promise. when the promise is resolved then I get the value and call addAlert() function which is an API POST request.

The problem here is the code works but the API has a rate limit of 1 request per second. I tried using setTimeout but it is not working because in my thinking, the promise are resolved very quickly and .then function is triggered bypassing the setTimeout().

I need help here so that even if all of the 50 promises are resolved with in a second, the addAlert() method should be called once a sec. I have tried using setTimeout out of the $.each iteration, inside the .then ; nothing helps.

Any Help is appriciated ! Thanks


Solution

  • Put the calls to your API in a queue that fires every 1 second:

    // Variables holding the timeout id (for cancelling) and queue to process
    var queueId;
    var q = [];
    
    // This is the "run" function. 
    function runQueue() {
    
      // If the queue has any items on it, then let's process one
      if (q.length > 0) {
    
        // Pull the first item off the queue (Last in, first out)
        var f = q.shift();
    
        // Run it as a function (could probably benefit from a 'typeof' check)
        if (typeof f === "function") {
          f();
        }
      }
    
      // Set this very function to run again in 1s.
      queueId = setTimeout(runQueue, 1000);
    }
    
    // Stop the queue processing
    function stopQueue() {
      clearTimeout(queueId);
    }
    
    // Start the queue .. the actual queue may be empty, but that won't
    // bother the process as it will simply set itself up to run again
    // in a second
    runQueue();
    
    $.each(result[1], function(i, coin) {
    
        var coincalcClass = new coincalculationClass();
    
        // this method returns a promise.
        var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);
    
        highforMonth.then(function(value) {
            var market_name = coin.mktName;
            var bestPrice = value['1'];
            q.push(function() { 
              addAlert('BTRX', market_name, bestPrice);
            });
        );
    });
    

    Edit: this really is a quick and dirty implementation of a queue. My personal favorite is p-queue which implements rate limiting and other nifty features.