使用节点和火库循环访问数千条记录

Looping through thousands of records using node and firebase

本文关键字:记录 千条 访问 节点 循环      更新时间:2023-09-26

我的Firebase数据存储中有大约10,000条记录,每条记录都附加了一些数据,例如。

productName: {
 price: 10.00,
 lastChecked: timestamp,
 url: 'http://product/url',
 imagePath: 'http://product/image/url'
}

我遍历每个产品,它检索到每个产品数据,然后执行其他任务。

当我只有几百条记录时,我让它全部工作,但现在我有数千条(还有更多(,当我运行任务时,它会崩溃 du 到 CPU 过载,并且大多数产品不执行其任务。

我已经阅读了有关循环阻塞的信息,并尝试了回调中的超时,我在几篇文章中读到了这些帖子,这些帖子有所改进,但尚未设法防止服务器CPU过载。

这是我从另一篇文章中实现的示例。

        getProductData = function(product, callback){
            ref.child('products/'+product).once('value', function(snapshot) {
                    callback(snapshot.val(), product);
                });
            },
        queryProductData = function(product){
            getProductData(product, function (productData, productKey) {                    
                 setTimeout(scrapeProductDetails(product), 2000) //queue for next ping in the next predefined interval
            });
        },
        productLoop = function(productsList) {                
            for (var product in productsList)
            {
                setTimeout(queryProductData(product), 2000) //queue job. Every 2 seconds, query_host will be called.
            }
        }

这是作为 Node 服务而不是网站运行的,因此将在后台运行。

关于这一点:

for (var product in productsList)
{
    setTimeout(queryProductData(product), 2000)
}

这里有两件事不太对劲:

  • 通过执行setTimeout(queryProductData(product), 2000),您已经在计时器启动之前运行了该函数。研究bind来解决这个问题。

  • for 循环一次遍历每个产品并创建计时器,因此每个计时器将在同一时刻启动。结果:for 循环后 2 秒,所有函数将同时运行。所以你基本上仍然一次做所有事情,但你增加了 2 秒的延迟。

您可能想要的是这样的结构:

index = 0
function nextProduct() {
    productName = productsList[index] // get current product from list
    // Do what you need with productName
    index++ // Next product
}
setInterval(nextProduct, 2000);

nextProduct每次调用时都会从列表中获取下一个产品,并且setInterval每 2 秒重复调用nextProduct一次。

上述注意事项:如果同步运行nextProduct需要 2 秒以上,则在调用下一个函数时可能不会更新index,因此最好在使用它获取产品名称后立即更新index,而不是像我的示例那样在最后更新。

另一种解决方案是让nextProduct完成后调用自己,而不是使用 setInterval .但是,在使用递归函数时,您需要克服其他问题(例如堆栈大小限制(,因此我建议您不要将其用于您的用例。

我希望我的回答对您有所帮助,如果不能随意发表评论,我会再看看它。