1

私はnodejsを学んでいます。非同期関数がどのように機能するかを理解するのに苦労しています。私の質問は、以下のコードに関連しています。次のことをまったく同じ順序で実行しようとしています。

  1. ファイル a.txt を開きます。
  2. それを読んで。
  3. その内容を印刷します。
  4. ファイルを閉じて、ファイルが閉じられたことを記録します。
  5. もう一度開きます。
  6. 新しいコンテンツで上書きします。

問題は、私が得ている出力によると、これらのイベントのシーケンスを制御していないように見えることです。これは、コンソールに表示される出力です。

21 バイトを読み取りました / これは私のテスト ファイルです / 30 バイトを書き込みました / ファイルを閉じて、書き込みの準備ができました

ご覧のとおり、何らかの理由で、ファイルが閉じられたことをログに記録する前に、プログラムがファイルに書き込みを行っています。私はそれを閉じようとしていて、閉じられたことを記録してからファイルに書き込もうとしていました。

ですから、イベントの流れを制御するのに問題があると思います。私が間違っていることを指摘できますか?

これはコードです:

var fs = require('fs');

//What I am trying to do here is: open a file a.txt, read it, print its content and then //close the file and log that it has been closed.
//Then, open it again and overwrite it.

fs.open('a.txt', 'r', function(err, fd){
    if(err){throw err;}
    var readBuffer = new Buffer(1024);
    var bufferOffset = 0;
    var filePosition = 0;
    var readBufferLength = readBuffer.length;

    fs.read(fd, readBuffer, bufferOffset, readBufferLength, filePosition, function(err, readBytes){
    if(err){throw err;}
    console.log('just read ' + readBytes + ' bytes');
    console.log(readBuffer.slice(0,readBytes).toString());
    fs.close(fd,function(){
        console.log('file close and ready for write');
    });
    });




});


fs.open('a.txt', 'r+', function(err,fd){
    if(err){throw err;}
    var writeBuffer = new Buffer('saul lugo overwrote this file!');
    var bufferOffset = 0;
    var writeBufferLength = writeBuffer.length;
    var filePosition = null;

    fs.write(fd, writeBuffer, bufferOffset, writeBufferLength, filePosition, function(err, writeBytes){
    if(err){throw err;}
    if(writeBytes>0){
        console.log('just wrote ' + writeBytes + ' bytes.');
    }
    });
});
4

2 に答える 2

1

これらの操作はすべて非同期であるためfs.open('a.txt', 'r+')、コードの最上位で呼び出すことはできません。直後に呼び出されるfs.open('a.txt', 'r')ため、予期しない結果が得られます。

writeToAFile()first のコールバックで呼び出されているのを見てくださいfs.close()。これは、ファイルが最初に読み取られ、閉じられ、次に書き込まれて閉じられることを確認するための鍵です。

ここに修正があります:

var fs = require('fs');

fs.open('a.txt', 'r', function(err, fd){
    // do stuff ...

    fs.read(/* params */, function(err, readBytes){
      // do stuff ...

      fs.close(fd,function(){
        // now open file again for writing
        writeToAFile();
      });
    });
});

// This will be called inside the callback handler for closing the file.
// This way file will be opened for reading, read, close and THEN opened for writing.
function writeToAFile () {
  fs.open('a.txt', 'r+', function(err,fd){
    // do stuff ...

    fs.write(/* params */, function(err, writeBytes){
      // do stuff ...

      // close file
    });
  });
}
于 2013-08-27T20:08:04.410 に答える
1

fs.open を再度呼び出す前に、手順 4 が完了するまで待つ必要があります。

今、あなたのコードは次のようになります

fs.open("a.txt", function(){
    foo(function(){
       console.log("done with first file")
    })
});

fs.open("a.txt", function(){
    foo(function(){
      console.log("done with second file")
    })
});

順序を維持するには、関数をネストする必要があります。

fs.open("a.txt", function(){
    foo(function(){
       console.log("done with first file")

       fs.open("a.txt", function(){
           foo(function(){
               console.log("done with second file")
           })
        });
    })
});

もちろん、これは非常に見苦しく、4 レベル以上の深さをネッティングするのは読みにくいです。追加の名前付き関数を作成することで、見た目を少し良くすることができます

  console.log("done with first file");
  doThingsWithSecondFile();

または、async.js や promises などのライブラリを調べることもできます。(これらのライブラリは、デフォルトでより適切なエラー処理が必要な場合に特に役立ちます)

于 2013-08-27T20:09:40.247 に答える