Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.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 延迟函数执行(API调用)以在时间段内执行n次_Javascript_Node.js - Fatal编程技术网

Javascript 延迟函数执行(API调用)以在时间段内执行n次

Javascript 延迟函数执行(API调用)以在时间段内执行n次,javascript,node.js,Javascript,Node.js,我正在尝试编写后端功能来处理特定API的请求,但此API有一些限制性配额,尤其是每秒请求。我想创建一个API抽象层,如果有太多的请求,它可以延迟函数执行,因此它的工作原理如下: 新请求到达(简单地说,是调用了库方法) 根据给定的限制(请求数),检查是否可以立即执行此请求 如果无法执行,请将其执行延迟到下一个可用的时刻 如果此时新请求到达,则进一步延迟其执行或将其置于某个执行队列中 我在等待队列长度方面没有任何限制。请求是函数调用,node.js回调是用数据响应的最后一个参数 我曾想过为每个请求添

我正在尝试编写后端功能来处理特定API的请求,但此API有一些限制性配额,尤其是每秒请求。我想创建一个API抽象层,如果有太多的请求,它可以延迟函数执行,因此它的工作原理如下:

  • 新请求到达(简单地说,是调用了库方法)
  • 根据给定的限制(请求数),检查是否可以立即执行此请求
  • 如果无法执行,请将其执行延迟到下一个可用的时刻
  • 如果此时新请求到达,则进一步延迟其执行或将其置于某个执行队列中
  • 我在等待队列长度方面没有任何限制。请求是函数调用,node.js回调是用数据响应的最后一个参数

    我曾想过为每个请求添加延迟,这将等于请求之间可能存在的最小时隙(表示为最小毫秒/请求),但这可能有点低效(总是在发送响应之前延迟函数)


    您知道有什么库或简单的解决方案可以为我提供这样的功能吗?

    保存最后一个请求的时间戳

    每当您有一个新的传入请求时,请检查此后是否经过了最小间隔,如果没有,请将函数放入队列中,然后安排作业(除非已经安排了作业):


    processItemFromQueue
    从队列前面(
    shift
    )获取作业,然后重新调度自身,除非队列为空。

    此问题的确切答案(以及最佳答案)来自API文档本身。我们用了几个月,它完美地解决了我的问题

    在这种情况下,最好的方法不是编写一些复杂的队列代码,而是利用JS处理异步代码的可能性,自己编写简单的回退,或者使用许多优秀的库中的一个来使用它

    因此,如果您偶然发现任何API限制(例如配额、5xx等),您应该使用回退再次递归运行查询,但延迟会越来越大(有关回退的更多信息可在此处找到:)。最后,如果在给定的次数后再次失败,则优雅地返回关于API不可用的错误

    以下使用示例(摘自):


    nodej有许多回退库,利用承诺风格、回调风格甚至事件风格的回退处理(上面的例子是第二个提到的例子)。如果您了解退避算法本身,它们非常容易使用。由于退避参数可以存储在配置中,如果退避失败太频繁,可以对其进行调整以获得更好的结果。

    如果是我,我不会对请求进行任何排队,相反,我会告诉客户端无法处理该请求。这纯粹是后端功能,因此每个请求都必须作为更大流程的一部分来完成-只能因为配额限制而延迟。429请求太多,但总是有一个客户端。客户端>服务器-客户端并不总是用户。在应用程序中执行队列管理感觉不对劲。如果队列不断增长怎么办?暂停时间呢?失败的尝试怎么办?试一试怎么样?也许使用合适的队列?
    setTimeout(
      processItemFromQueue,
      (lastTime + minInterval - new Date()).getTime()
    )
    
    var call = backoff.call(get, 'https://someaddress', function(err, res) {
        console.log('Num retries: ' + call.getNumRetries());
    
        if (err) {
            // Put your error handling code here.
            // Called ONLY IF backoff fails to help
            console.log('Error: ' + err.message); 
        } else {
            // Put your success code here
            console.log('Status: ' + res.statusCode);
        }
    });
    
    /*
     * When to retry. Here - 503 error code returned from the API
     */
    call.retryIf(function(err) { return err.status == 503; }); 
    
    /*
     * This lib offers two strategies - Exponential and Fibonacci. 
     * I'd suggest using the first one in most of the cases
     */
    call.setStrategy(new backoff.ExponentialStrategy());
    
    /*
     * Info how many times backoff should try to post request
     * before failing permanently
     */
    call.failAfter(10);
    
    // Triggers backoff to execute given function
    call.start();