0

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

如何将此代码放在 for 循环中,每次循环迭代32将更改为641282565121024 ?

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 循环回调未按预期工作TLDR:因为 node.js 和 javascript 是单线程的。

4

3 回答 3

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);
    });
}
于 2013-06-14T00:49:37.073 回答
1

使用数组?我不确定我是否正确理解了您的问题,因为此解决方案似乎很愚蠢...

// 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);
    });
}
于 2013-06-14T00:54:19.487 回答
0

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

但是之前的两个答案都有一个错误。他们在回调中使用filepathwritestream变量,但是,在循环完成执行imageStream32.on('close'),此回调被异步调用。因此,所有这些回调都使用这两个变量最后一次通过循环接收到的最后一个值,而不是来自正确循环迭代的正确值。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 );
于 2013-06-14T06:02:26.020 回答