【问题标题】:Best practice for sequential url requests nodejs顺序 url 请求的最佳实践 nodejs
【发布时间】:2018-05-25 23:46:24
【问题描述】:

我有一个需要从 API 请求的 url 列表,但是为了避免造成大量负载,我希望以 x 秒的间隔执行这些请求。一旦所有的请求都完成了,一些无关紧要的逻辑就会随之而来。

有很多方法可以解决,我已经实现了几个。

A) 使用递归函数遍历包含所有 url 的数组并在每个请求完成并发生超时时调用自身

B) 为循环中的每个请求设置超时,并增加延迟并返回 Promise,在使用 Promise.all 解决时执行其余逻辑等等。

这些都有效。但是,您会说什么是推荐的解决方法?这更像是一个学术类型的问题,当我这样做是为了学习时,我宁愿避免使用抽象果汁的库。

【问题讨论】:

  • 你确定拆分它有什么好处吗?虽然留出空间不会同时进行所有加载,但发送和接收的数据总量不会改变,只要总加载时间小于秒,就不会有人注意到任何事情。
  • 推荐的方式可能意味着很多事情。你的意思是性能方面吗?您的意思是实施起来有困难吗?
  • recommended way - 我想说,在 A 或 B 这两个中,我可能会在生产环境中选择,我不会使用这两个“模式”跨度>
  • -在 Akxe,每个请求都会触发一个非常繁重的处理过程,因此负载实际上不在网络中,而是在 CPU 中。 -在 maxpaj 我应该对此更具体。我的意思是好的代码。我的解决方案对我来说似乎很老套,但我不知道我不知道什么。 -在 JaromandaX 没有冒犯,但你告诉我的只是“不要使用那些”,而不是为什么或提供更好的选择:/
  • A 解决方案不保证每个周期开始 x 数量,它会开始 x 数量,当它们完成后开始另一个 x 数量。解决方案 B 是我在回答中使用的,但在名为 later 的函数中使用超时,并安排在最早可用时间返回承诺的函数。每个时期的计划允许每个时期的 x 数量,并且不在乎它们何时完成。但是您也可以限制活动,这将不允许超过 x 数量的活动,并且当一个解决另一个开始时。

标签: javascript node.js promise


【解决方案1】:

您的解决方案几乎相同。以为我会选择一种不同的方法。我会做出初始承诺和睡眠承诺功能,然后将它们链接在一起。

function sleep(time){
    return new Promise(resolve => setTimeout(resolve, ms));
}

ApiCall()
.then(sleep(1000))
.then(nextApiCall())...

或更多模块化版本

var promise = Promise.resolve()
myApiCalls.forEach(call => {
    promise = promise.then(call).then(() => sleep(1000))
})

最后,按照你理解的、最有意义的以及你在一个月内会理解的内容去做。您可以阅读的最佳解决方案是您首选的解决方案,性能在这里无关紧要。

【讨论】:

  • 应该有 async/await 的可能解决方案,女巫可能很简洁,但我想不通...
  • 感谢您的回复。这是出于学习目的而不是生产目的,所以我主要是在寻找一种更易读、更优雅的编码方式,就像你建议的那样,而不是过多地追求性能,因为正如你所说,无论如何它可能不会有显着差异
【解决方案2】:

您可以在每个期间使用这样的东西来throttle

如果您希望即使有些失败也能处理所有 url,您可以捕获失败的那些并在结果中挑选出来。

代码看起来像这样:

const Fail = function(details){this.details=details;};
twoPerSecond = throttlePeriod(2,1000);
urls = ["http://url1","http://url2",..."http://url100"];
Promise.all(//even though a 100 promises are created only 2 per second will be started
  urls.map(
    (url)=>
      //pass fetch function to twoPerSecond, twoPerSecond will return a promise
      //  immediately but will not start fetch untill there is an available timeslot
      twoPerSecond(fetch)(url)
      .catch(e=>new Fail([e,url]))
  )
)
.then(
  results=>{
    const failed = results.map(result=>(result&&result.constuctor)===Fail);
    const succeeded = results.map(result=>(result&&result.constuctor)!==Fail);
  }
)

【讨论】:

    猜你喜欢
    • 2021-05-07
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多