Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 定时承诺队列/限制_Javascript_Queue_Promise_Bluebird_Rate Limiting - Fatal编程技术网

Javascript 定时承诺队列/限制

Javascript 定时承诺队列/限制,javascript,queue,promise,bluebird,rate-limiting,Javascript,Queue,Promise,Bluebird,Rate Limiting,我有一个向API发出请求的函数。我受此API的速率限制,不断收到错误消息: Exceeded 2 calls per second for api client. Reduce request rates to resume uninterrupted service. 我并行运行了两个循环,如果我只运行一个实例,那么就会出现问题。在这些调用中,它们会导致调用相同的函数a。我想用另一个队列函数包装此函数,并将间隔设置为500毫秒,以便请求不会在队列上一个接一个或并行发出,而是设置为该时间。问题

我有一个向API发出请求的函数。我受此API的速率限制,不断收到错误消息:

Exceeded 2 calls per second for api client. Reduce request rates to resume uninterrupted service.
我并行运行了两个循环,如果我只运行一个实例,那么就会出现问题。在这些调用中,它们会导致调用相同的函数a。我想用另一个
队列
函数包装此函数,并将间隔设置为
500
毫秒,以便
请求
不会在队列上一个接一个或并行发出,而是设置为该时间。问题是,我仍然需要这些承诺来获得它们的内容,即使需要相当长的时间才能得到回应

有什么可以帮我的吗?我可以把一个函数包装起来,它会以设定的时间间隔响应,而不是并行响应,或者一个接一个地启动函数

更新:也许它确实需要特定于承诺,我尝试使用下划线的throttle函数

var debug = require("debug")("throttle")
var _ = require("underscore")
var request = require("request-promise")

function requestSite(){
  debug("request started")
  function throttleRequest(){
    return request({
      "url": "https://www.google.com"
    }).then(function(response){
      debug("request finished")
    })
  }
  return _.throttle(throttleRequest, 100)
}

requestSite()
requestSite()
requestSite()
我得到的只是这个:

$ DEBUG=* node throttle.js 
throttle request started +0ms
throttle request started +2ms
throttle request started +0ms
更新

最后一个答案是错误的,这很有效,但我仍然认为我可以做得更好:

// call fn at most count times per delay.
const debounce = function (fn, delay, count) {
    let working = 0, queue = [];
    function work() {
        if ((queue.length === 0) || (working === count)) return;
        working++;
        Promise.delay(delay).tap(() => working--).then(work);
        let {context, args, resolve} = queue.shift();
        resolve(fn.apply(context, args));
    }
    return function debounced() {
        return new Promise(resolve => {
            queue.push({context: this, args: arguments, resolve});
            if (working < count) work();
        });
    };
};

function mockRequest() {
    console.log("making request");
    return Promise.delay(Math.random() * 100);
}

var bounced = debounce(mockRequest, 800, 5);
for (var i = 0; i < 5; i++) bounced();
setTimeout(function(){
    for (var i = 0; i < 20; i++) bounced();
},2000);
现在,makeRequest调用将至少相隔1000毫秒

jfriend指出,每秒需要两个请求,而不是一个请求-这同样可以通过第二个队列轻松解决:

var p = Promise.resolve(1); // our first queue
var p2 = Promise.resolve(2); // our second queue

function makeRequest(){

    var turn = Promise.any([p, p2]).then(function(val){ 

        // add 1000 ms delay to queue so the next caller has to wait 
        // here we wait for the request too although that's not really needed, 
        // check both options out and decide which works better in your case
        if(val === 1){
            p = p.return(turn).delay(1, 1000);
        } else {
            p2 = p2.return(turn).delay(1, 1000); 
        }
        return request("http://www.google.com");
    });

    return turn; // return the actual promise
};

这可以概括为
n
承诺使用类似的数组

你能给我们展示一些你的实际代码以便我们使用吗?@jfriend00我的实现非常特定于一个API。我所拥有的是一个用于
请求
的包装器,许多函数都使用它。这就是我能控制的点。我想用某种排队函数包装包含
请求的包装器。这类问题的一般解决方案:。高效的每秒2次调用比这要复杂一些。例如,您应该能够立即发送2个呼叫,但如果第三个呼叫立即到来,则必须等待一秒钟,如果第三个呼叫稍后到来,则必须等待一秒钟。@jfriend00我已更新了答案-感谢再次注意。
p=p.then(function(){return Promise.delay(1000);})
可以写成
p=p.delay(1000)
p=p。然后(function(){return turn})
可以写成
p=p.return(turn)
,依此类推。。jesus man学习api:d第二个看起来不正确,
queueId
总是
undefined
,除了处理请求所需的时间外,您还需要等待1秒。我实际上无论如何都无法让它工作,我想最好实现标准算法。顺便说一句,延迟实例方法只需要一段时间,并通过以前的实现值,而不是采用自定义值。所以
。延迟(1000)。返回(1)
var p = Promise.resolve(1); // our first queue
var p2 = Promise.resolve(2); // our second queue

function makeRequest(){

    var turn = Promise.any([p, p2]).then(function(val){ 

        // add 1000 ms delay to queue so the next caller has to wait 
        // here we wait for the request too although that's not really needed, 
        // check both options out and decide which works better in your case
        if(val === 1){
            p = p.return(turn).delay(1, 1000);
        } else {
            p2 = p2.return(turn).delay(1, 1000); 
        }
        return request("http://www.google.com");
    });

    return turn; // return the actual promise
};