需要在 promise 解决后每 2 秒向 API 发送请求,在有限循环中运行

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

我会尽力解释我的问题。

我有 javascript Promise,2 API 和 setTimeout 正在运行。

    $.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

    });

所以,在代码中,首先我有一个 json 值,(50 个值),我将遍历每个值。 我在做一些计算。 我调用 returns 承诺的 getHighLowForSpecificDays() 方法。当承诺得到解决时,我得到值并调用 addAlert() 函数,这是一个 API POST 请求。

这里的问题是代码有效,但 API 的速率限制为每秒 1 个请求。我尝试使用 setTimeout,但它不起作用,因为在我看来,承诺很快得到解决,然后绕过 setTimeout() 触发函数。

我在这里需要帮助,这样即使一秒钟内解决了所有 50 个承诺,也应该每秒调用一次 addAlert() 方法。我尝试在 .then 中的 $.each 迭代中使用 setTimeout;没有任何帮助。

任何帮助都适用! 谢谢

将对您的 API 的调用放入每 1 秒触发一次的队列中:

// 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);
        });
    );
});

编辑:这确实是一个快速而肮脏的队列实现。我个人最喜欢的是 p-queue,它实现了速率限制和其他漂亮的功能。

您似乎需要的是能够以 最小 1 秒间隔计量对 API 的请求,换句话说:

  • 如果 API 在 1 秒内响应,那么下一个请求应该在上一个请求之后延迟到 1 秒。
  • 如果 API 响应时间超过 1 秒,则可能会立即发出下一个请求。

这是一个通用的异步递归函数,它就是这样做的:

function recurseAsync(arr, fn, initialValue, minimumInterval) {
    var index = 0;
    var arr_ = arr.map(function(x) { return x }); // clone array (safety measure)
    function delay(t) {
        return $.Deferred(function(dfrd) {
            setTimeout(dfrd.resolve, t);
        });
    }
    function recurse(previous) {
        return (index < arr_.length) ? 
            $.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse) :
            previous;
    }
    return recurse(initialValue);
}

规则的实施非常简单。表达式 $.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse) 确保仅当 fn() 调用已解决且最小延迟已发生时才调用 recurse。这是一种奇怪的比赛,最后一个回家的人为下一场比赛打发令枪。

coincalcClass 的用法API:

function getCoinData(previous, current) {
    var coin = current;
    var coincalcClass = new coincalculationClass();
    return coincalcClass.getHighLowForSpecificDays(coin.mktName, 3)
    .then(function(value) {
        var market_name = coin.mktName;
        var bestPrice = value['1'];
        addAlert('BTRX', market_name, bestPrice);
        return null; // appears as `previous` at next call
    });
}

recurseAsync(result[1], getCoinData, null, 1000);

备注:

  • recurseAsync() 在概念上与 Array#reduce() 类似,但它是作为函数而不是方法编写的,并且接受 minimumInterval 参数(默认为 0)。
  • previous 未在此示例中使用,并使用 null.
  • 初始化