优雅的方式运行大量异步“;事物;当总数为'直到第一个“;事物;退货

Elegant way to run a lot of asynchronous "things" in batches in a loop when the total isn't known until the first "thing" returns?

本文关键字:事物 退货 第一个 运行 异步 方式      更新时间:2023-09-26

我正在处理的问题是在所有页面(问题、标签等等)上调用Stack Exchange API(1.1)。但事实上,这似乎也是一个普遍的问题,所以我在这里发帖,而不是在StackApps上。

因此,简单的方法是进行一个初步调用,只获取总数,然后将其余部分放入循环中。

但这个第一个调用实际上也可以获取结果的第一页并保存一个调用。

但是,将第一次调用作为特殊情况似乎比上面的"简单方法"更复杂。

这很复杂,因为我可以一次获取多个页面,但由于速率限制,不能全部获取。

如果jQuery提供了任何有用的东西,我将使用JavaScript。

以下是我想到的一些伪代码,但我还没能让它工作:

batch_num = 0
batch_size = 1 // how many pages to fetch in each batch. 1st is just 1 so we know the total
forever {
  get_batch (batch_size)
  if (batch_num == 0) {
    calculate batch_num to use from now on based on the total number of pages and the rate limits
  }
  if (batch_num == last) {
    break
  }
  ++ batch_num
}
exit
function get_batch (batch_size) {
  for (i = 0; i < batch_size; ++i) {
    getJSON next page
  }
}

代码过于简单化,因为异步回调中的内容很重要,会使代码变得更加复杂和难以阅读。

我尝试过迭代和递归方法,但无法理解细节。

那么,尽管需要额外的异步调用,"简单方法"是最好的方法吗?或者,真的有一种方法可以让像我的伪代码这样优雅而不是复杂的东西发挥作用吗

(如果你觉得这太专业化了,不能概括属于SE API,那么我很乐意将其迁移到StackApps。)

在提出这个问题一段时间后,我终于进入了node.js,在这里处理异步代码可以说比浏览器JavaScript更重要。

"caolan"的Async.js是最流行的模块/库之一,它可以简化异步控制流和容器上的迭代。

它包括三个支持批处理的功能:

  • eachLimit(arr, limit, iterator, callback)
  • mapLimit(arr, limit, iterator, callback)
  • parallelLimit(tasks, limit, [callback])

limit-任何时候要运行的迭代器/任务的最大数量。

我想说,在99%的情况下,你应该选择简单的方法。

考虑一下,如果你得到100的计数,你将进行101次调用,而不是100次,这不值得代码复杂化,如果你以后需要更改逻辑,你可能会后悔。