2017-08-31 41 views
2

のために、私は以下のコードを複数のファイルにデータ収集をストリーミングしようとしていますで、前のストリームを上書き:ノード - 読み取り可能なストリームパイプ()ループ

for (var key in data) { 
    // skip if collection length is 0 
    if (data[key].length > 0) { 
    // Use the key and jobId to open file for appending 
    let filePath = folderPath + '/' + key + '_' + jobId + '.txt'; 

    // Using stream to append the data output to file, which should perform better when file gets big 
    let rs = new Readable(); 
    let n = data[key].length; 
    let i = 0; 

    rs._read = function() { 
     rs.push(data[key][i++]); 

     if (i === n) { 
     rs.push(null); 
     } 
    }; 

    rs.pipe(fs.createWriteStream(filePath, {flags: 'a', encoding: 'utf-8'})); 

    } 
} 

はしかし、私は、移入されたすべてのファイルを取得して終了同じデータで、dataオブジェクトの最後のキーの配列です。リーダーストリームは各ループでオーバーライドされ、pipe()から書き込み可能ストリームはforループが終了するまで開始されません。そんなことがあるものか?

+0

が – Kieper

答えて

1

rs._readメソッドが非同期に呼び出され、キー変数が関数スコープである(varキーワードのために)ため、コードがおそらく動作しない理由があります。

作成するすべてのrsストリームは、キーと同じ変数をポイントしますが、メインループの最後では、これらのコールバックはそれぞれ同じ値になります。 "var"を "let"に変更すると、各反復で新しいキー変数が作成され、問題を解決します(_read関数は共有変数の代わりにキー変数の独自のコピーを持ちます)。

変更すると動作するようにしてください。

+0

感謝をできるように最初のループでのVARのために変更してみてください、私はいつも疑問に思ってきた。それで私たちは、私はコードよりクリーンで再利用可能なを作るためにリファクタリングのビットを提案することができますしながら

varとletの違いは何ですか?それは本当に問題でした。このような状況になるまで、ブロッキングコードを同期して実行すると問題はないようです。したがって、ループが完了するまで、すべてのコールバックが待機しているように見えます。 – StephenK

0

これはループ文で定義しているkeyがブロックスコープではないために起こります。これは最初は問題ではありませんが、rs._read関数内にクロージャを作成すると、それ以降のすべてのストリームの読み込みでは最後の値がdata配列の最後の値を使用しています。

const writeStream = (folderPath, index, jobId) => { 
    const filePath = `${folderPath}/${index}_${jobId}.txt`; 

    return fs.createWriteStream(filePath, { 
     flags: 'a', encoding: 'utf-8' 
    }); 
} 

data.forEach((value, index) => { 
    const length = value.length; 

    if (length > 0) { 
     const rs = new Readable(); 
     const n = length; 

     let i = 0; 

     rs._read =() => { 
      rs.push(value[i++]); 
      if (i === n) rs.push(null); 
     } 

     rs.pipe(writeStream(folderPath, index, jobId)); 
    } 
}); 
+0

ありがとうございます。ノードへの初心者、私はまだコールバックと文法の周りに自分の道を感じています。この非同期シナリオでは、読み取りストリームと書き込みストリームオブジェクトはどのようにガベージコレクトされますか?ストリーム終了(ヌル)文字はこれらのオブジェクトの終了をトリガーしますか?また、これらのイベントを連鎖させたい場合、たとえば、ファイルコピー機能は、すべてのファイルへの書き込みが完了するまで実行されません。どのように達成するのですか? – StephenK

関連する問題