3

node.jsが非同期呼び出しの開始/完了の順序を保証するかどうか疑問に思っています。

私はそうは思いませんが、非同期呼び出しが予期した順序で完了しない可能性があるため、バグがあると思われるインターネット上のコードサンプルをいくつか読みましたが、例はノードがどれほど優れているかという文脈で述べられていることがよくありますシングルスレッドの非同期モデルのためです。ただし、この一般的な質問に対する直接的な答えは見つかりません。

異なるノードモジュールが異なる保証をするという状況ですか? たとえば、https://stackoverflow.com/a/8018371/1072626の回答では、Redis を含む非同期呼び出しが順序を保持していると明確に述べています。

この問題の核心は、次の実行 (または類似の実行) がノードで厳密に安全であるかどうかに要約できます。

var fs = require("fs");
fs.unlink("/tmp/test.png");
fs.rename("/tmp/image1.png", "/tmp/test.png");

作成者によると、unlink既存のファイルがある場合、Windows では名前の変更が失敗するため、への呼び出しが必要です。ただし、どちらの呼び出しも非同期であるため、非同期操作が開始される前に非同期 I/O が確実に完了するように、への呼び出しをrenameのコールバックに含める必要があると最初に考えました。unlinkrenamerename

4

2 に答える 2

4

非同期操作には、実行する時間が決まっていません。

を呼び出すとunlink、OS にファイルを削除するように要求されますが、OS が実際にいつファイルを削除するかは定義されていません。1 ミリ秒後または 1 年後かもしれません。

非同期操作の要点は、明示的に明記されていない限り、相互に依存しないことです。

renameの後に発生させるにunlinkは、次のようにコードを変更する必要があります。

fs.unlink("/tmp/test.png", function (err) {
    if (err) {
        console.log("An error occured");
    } else {
        fs.rename("/tmp/image1.png", "/tmp/test.png", function (err) {
            if (err) {
                console.log("An error occured");
            } else {
                console.log("Done renaming");
            }
        });
    }
});

または、代わりに fs 関数の同期バージョンを使用するには (これらは実行中のスレッドをブロックすることに注意してください):

fs.unlinkSync("/tmp/test.png");
fs.renameSync("/tmp/image1.png", "/tmp/test.png");

非同期コードの見栄えを良くする asyncなどのライブラリもあります。

async.waterfall([
    fs.unlink.bind(null, "/tmp/test.png");
    fs.rename.bind(null, "/tmp/image1.png", "/tmp/test.png");
], function (err) {
    if (err) {
        console.log("An error occured");
    } else {
        console.log("done renaming");
    }
});

すべての例で、アイデアを表すためにエラー処理が非常に単純化されていることに注意してください。

于 2012-06-28T04:33:51.280 に答える
1

Node.js のドキュメントを見ると、関数 fs.unlink が次のように引数としてコールバックを受け取ることがわかります。

 fs.unlink(path, [callback]);

現在の関数が戻るときに実行する予定のアクションは、コールバック引数として関数に渡す必要があります。したがって、通常、コードは次の形式になります。

 var fs = require("fs");
 fs.unlink("/tmp/test.png", function(){
     fs.rename("/tmp/image1.png", "/tmp/test.png");
 });

リンク解除と名前変更の特定のケースでは、Node.js にも同期関数があり、fs.unlinkSync(path) および fs.renameSync(oldPath, newPath) として使用できます。これにより、コードが同期的に実行されます。

さらに、非同期実装を使用したいが読みやすさを維持したい場合は、asyncのようなライブラリを検討できます。また、パラレル、シリーズ、ウォーターフォールなど、さまざまな実装モードのオプションもあります。

お役に立てれば。

于 2012-06-28T04:33:17.723 に答える