【问题标题】:How to iterate over the following code inside a for-loop?如何在 for 循环中迭代以下代码?
【发布时间】:2023-03-25 09:51:01
【问题描述】:

我有以下代码,它抓取 6 个 URL 之一,剥离文件名,创建文件路径,将图像文件保存到磁盘,将其发送到 MongoDB GridFS。唯一改变的是图像大小:32px、64px、128px、256px、512px、1024px。 Bruteforce 方法就是复制粘贴这段代码 6 次,你可以想象那会是多么的一团糟。

如何将此代码放在 for 循环中,其中 32 会更改为 64128256, 512, 1024 每次循环迭代?

var filename32 = image32.replace(/^.*[\\\/]/, '');
var filepath32 = path.join(__dirname, filename32);
var writestream32 = gfs.createWriteStream({ filename: filename32 });
var imageStream32 = request(image32).pipe(fs.createWriteStream(filepath32));

imageStream32.on('close', function() {
  fs.createReadStream(filepath32).pipe(writestream32);
  fs.unlink(filepath32);
});

更新。

好的,所以这个问题不可能使用迭代方法来解决。更多信息在这里:node.js: while loop callback not working as expectedTLDR:因为 node.js 和 javascript 是单线程的。

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    这样的?我不确定实际上需要附加图像大小,我只是猜到了文件名。

    for(var i=32; i <= 1024; i*=2) {
        var filename = image.replace(/^.*[\\\/]/, '') + i;
        var filepath = path.join(__dirname, filename);
        var writestream = gfs.createWriteStream({ filename: filename });
        var imageStream = request(image).pipe(fs.createWriteStream(filepath));
    
        imageStream.on('close', function() {
          fs.createReadStream(filepath).pipe(writestream);
          fs.unlink(filepath);
        });
    }
    

    【讨论】:

    • 那里的“i”有什么用?
    • @Maresh 图像大小,例如filename32, filename64, filename128...您的方法更通用,而这个非常适合,因为每个大小都是 2 的倍数。
    • 我认为你对他的问题理解得不好,他说他有 6 个 url,所以有 6 个文件名。此处需要使用数组,您的代码将给出错误的文件名 IMO。
    • 使用数组可能会更健壮,但对于一个非常具体的情况,这会起作用。可能需要进行一些字符串操作才能将文件扩展名放在末尾,但这是相同的想法。
    • @bitwiser 它说图像未定义。我有 image32、image64、image128,它们是 URL。我试过image+iimage[i] 它没有评估它。仍然说图像未定义。
    【解决方案2】:

    使用数组?我不确定我是否正确理解了你的问题,因为这个解决方案看起来很傻......

    // use this array to store file names(urls).
        var imagesName = new Array("32.png", "128.png", "256.png", "512.png", "1024.png");
    
    for (var i = 0; i < imagesName.length; i++) {
        var filename = imagesName[i].replace(/^.*[\\\/]/, '');
        var filepath = path.join(__dirname, filename);
        var writestream = gfs.createWriteStream({ filename: filename });
        var imageStream = request(imagesName[i]).pipe(fs.createWriteStream(filepath));
    
        imageStream32.on('close', function() {
          fs.createReadStream(filepath).pipe(writestream);
          fs.unlink(filepath);
        });
    }
    

    【讨论】:

    • 看起来数组是解决这个问题的唯一方法。
    【解决方案3】:

    如果您所做的只是每次将大小加倍,则您不需要数组。正如@bitwiser 的回答所示,计算二的幂是微不足道的。

    但是前面的两个答案都有一个错误。他们在imageStream32.on('close') 回调中使用filepathwritestream 变量,但是,这个回调是异步调用的,for 循环完成执行之后。所以所有这些回调都使用这两个变量最后一次通过循环接收到的最后一个值,而不是来自正确循环迭代的正确值。

    解决这个问题很容易:您只需为每次循环迭代调用一个函数,而不是将代码直接放在循环体中。该函数调用创建了一个闭包,它为每个图像单独保留这些变量,因此您将为每个图像编写和关闭正确的文件。

    另外,您没有定义生成文件名的 image32 变量。你真的需要这里复杂的正则表达式吗?你不知道图像文件名应该是什么?我假设文件名是'image32''image1024',但你当然可以轻松更改它。

    所以代码应该是这样的:

    function processImages( basename, minSize, maxSize ) {
        for( var size = minSize;  size <= maxSize;  size *= 2 ) {
            processImage( size );
        }
    
        function processImage( size ) {
            var filename = basename + size;
            var filepath = path.join( __dirname, filename );
            var writestream =
                gfs.createWriteStream({ filename: filename });
            var imageStream =
                request(image).pipe( fs.createWriteStream(filepath) );
    
            imageStream.on( 'close', function() {
              fs.createReadStream(filepath).pipe(writestream);
              fs.unlink(filepath);
            });
        }
    }
    
    processImages( 'image', 32, 1024 );
    

    【讨论】:

      猜你喜欢
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      • 1970-01-01
      • 2014-08-13
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多