因此,我正在创建这个抓取应用程序,它本质上对服务器上的多个实体使用 REST API。主要功能就是:
let buffer = []
for(entity in entities){
let data = await scrapingProcessForAnEntity(entity);
buffer.push(data)
}
我过度简化了脚本,因为抓取过程及其存储方式并不相关,重点是我有这个函数
scrapingProcessForAnEntity
,它可以获取并返回 Promise 中我需要的所有信息。
问题是,由于有很多实体,我希望能够一次为多个实体运行该流程,一旦其中一个流程完成,一个新的流程就会取代它。我做了一些测试,尝试使用 Promise 数组和 Promise.race()
但我不知道如何使完成的 Promise 退出数组。
我当前的实现是:
let promises = []
let buffer = []
async function run(){
for(entity in entities){
addPromise(() => scrapingProcessForAnEntity(entity))
}
}
async function addPromise(prom){
if(promises.length >= 3){ //In this example I'm trying to make it run for up to 3 at a time
await moveQueue()
}
promises.push(prom())
}
async function moveQueue(){
if(promises.length < 3){
return
}
let data = await Promise.race(promises)
buffer.push(data)
promises.splice(promises.indexOf(data), 1) //<---- This is where I'm struggling at
//how can I remove the finished promised from the array?
}
将数据添加到缓冲区中并不是直接在 Promise 本身中实现,因为其中涉及处理,而且我不确定同时添加 2 个 Promise 中的数据是否会导致问题。
我还实现了一种最终清除所有承诺的方法。我唯一的困难是如何找到数组内的哪个 Promise 已完成,以便可以替换它。
你可以使用map方法来执行多个promise。例如
let allEntities = entities.map(item => {
return scrapingProcessForAnEntity(query)
});
const fullfilledPromises = Promise.all(promiseQuery)
这里 allEntities 将具有 Promise 数组,并且 Promise.all 方法将并行执行它
使用 Promise.all() 而不是 Promise.race()。这会返回一个 Promise,当所有输入 Promise 都已解决时,该 Promise 才会被解决。
let data = await Promise.all(promises)
buffer.push(data)
promises.splice(0, 3) //remove the first 3 promises from the array
它确保 Promises 全部同时运行,并且只有在所有 Promises 完成后才拼接数组。这也消除了跟踪哪个单独的 Promise 已完成的需要。