0

6 つの URL のいずれかを取得し、ファイル名を削除し、ファイルパスを作成し、画像ファイルをディスクに保存し、MongoDB GridFS に送信する次のコードがあります。変更されているのは画像サイズのみです: 32px、64px、128px、256px、512px、1024px。ブルートフォース アプローチは、このコードを 6 回コピー アンド ペーストするだけで、どれだけ混乱するか想像できます。

このコードを for-loop 内に配置するにはどうすればよいですか?ループの反復ごとに32641282565121024に変わりますか?

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 expected . 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

毎回サイズを 2 倍にするだけであれば、配列は必要ありません。@bitwiserの回答が示すように、2の累乗を計算するのは簡単です。

しかし、以前の回答には両方ともバグがあります。filepathコールバックで変数とwritestream変数を使用しimageStream32.on('close')ますが、このコールバックはループの実行が終了したに非同期で呼び出されます。forしたがって、これらのコールバックはすべて、適切なループ反復からの正しい値ではなく、これら 2 つの変数がループを通じて最後に受け取った最後の値を使用します。

これを修正するのは簡単です。コードをループ本体内に直接配置するのではなく、ループの反復ごとに関数を呼び出すだけです。関数呼び出しは、これらの変数を画像ごとに個別に保存するクロージャーを作成するため、画像ごとに正しいファイルを書き込んで閉じます。

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 に答える