node.js:从网址下载许多图片:超时因为太多的symultanous下载

问题描述 投票:3回答:2

我有代码从给定的URL下载图像。它遍历数据库中的产品,并为每个产品调用图像下载。

但是,一切似乎都是异步发生的,如果有太多的URL(要下载的图像),进程会因TIMEOUT而停止。这是合乎逻辑的,因为有大约3000个图像要下载。

你能否给我一些建议如何改进代码,以便它只下载“10”图像,并且在前一个“10”未完成时不开始下载下一个图像?我还不习惯node.js异步功能。

// download file
var download = function (uri, filename, callback) {
    request.head(uri, function (err, res, body) {
        request(uri).pipe(fs.createWriteStream(filename))
            .on('error', () => {
                console.log('Err');
            })
            .on('close', callback);
    })

};

// main code - looping through products in DB and upload file for each product (about 3000 products)

knex("products").select("products.id as id", "products.img as img", "products.code as code")       
    .mapSeries(function (product) {
            var imgName = 'imgs/' + product.code.toString() + ".png";
            download(product.img, imgName, function () {
                knex("products").where("id", product.id).update("img_path", imgName).then(() => {

                });
            });
        }
    })
    .then(() => {
        // console.log('done');
    });
node.js asynchronous download
2个回答
3
投票

使用async.eachOfLimit以按批处理Y元素继续执行X异步操作:

var async = require("async");

// products retrieved from bdd
var products = [{img: "http://www.google.fr/a", code:"yolo", id:1}, {img: "https://www.google.fr/b", code:"yolo2", id:2}];

async.eachOfLimit(products, 10, function(currentproduct, key, ecb){

    // function called for each products
     var imgName = 'imgs/' + currentproduct.code.toString() + ".png"; 
    download(currentproduct.img, imgName, function () {
                knex("products").where("id", currentproduct.id).update("img_path", imgName).then(() => {
                  // call next
                  ecb(null);
                });
            });

}, function(err){

   // final callback when all products has been proceed
   if(err)
   {
     // do stg
   }
   else
   {
     console.log("yeah");
   }
})

2
投票

我们有这些异步函数,例如限制

mapLimit(coll, limit(number), iteratee, callback)


async.mapLimit(['file1','file2','file3'], fs.stat, function(err, results) {
    // results is now an array of stats for each file
});

要么

eachLimit(coll, limit(number), iteratee, callback)

所以这将解决您的要求,因为这将在任何给定时间限制并行呼叫的数量

© www.soinside.com 2019 - 2024. All rights reserved.