53

以下のようにhttp関数から簡単なダウンロードを行いました(簡略化のためにエラー処理は省略されています):

function download(url, tempFilepath, filepath, callback) {
    var tempFile = fs.createWriteStream(tempFilepath);
    http.request(url, function(res) {
        res.on('data', function(chunk) {
            tempFile.write(chunk);
        }).on('end', function() {
            tempFile.end();
            fs.renameSync(tempFile.path, filepath);
            return callback(filepath);
        })
    });
}

ただし、非同期で何十回も呼び出すと、でファイルが見つからないという不平を言ってdownload()エラーが報告されることはめったにありません。fs.renameSynctempFile.path

Error: ENOENT, no such file or directory 'xxx'

同じ URL のリストを使用してテストしましたが、約 30% の確率で失敗しました。1つずつダウンロードすると、同じURLのリストが機能しました。

さらにテストしたところ、次のコードであることがわかりました

fs.createWriteStream('anypath');
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));

常に表示されるとは限りませんtrueが、最初の回答が表示されることがありますfalse

非同期fs.createWriteStream呼び出しが多すぎると、ファイルの作成が保証されないのではないかと思います。これは本当ですか?ファイルの作成を保証する方法はありますか?

4

4 に答える 4

74

ストリームからイベントを受け取るまで、書き込みストリームを呼び出さないwriteでください。そのイベントが表示されるまで、ファイルは存在しません。tempFile'open'

あなたの機能のために:

function download(url, tempFilepath, filepath, callback) {
    var tempFile = fs.createWriteStream(tempFilepath);
    tempFile.on('open', function(fd) {
        http.request(url, function(res) {
            res.on('data', function(chunk) {
                tempFile.write(chunk);
            }).on('end', function() {
                tempFile.end();
                fs.renameSync(tempFile.path, filepath);
                return callback(filepath);
            });
        });
    });
}

あなたのテストのために:

var ws = fs.createWriteStream('anypath');
ws.on('open', function(fd) {
    console.log(fs.existsSync('anypath'));
    console.log(fs.existsSync('anypath'));
    console.log(fs.existsSync('anypath'));
});
于 2012-10-16T02:42:34.567 に答える