1. ホーム
  2. node.js

[解決済み] Node.jsで複数のコールバックを待機させる慣用的な方法

2023-02-06 05:25:46

質問

ある一時ファイルに依存する操作を行う必要があるとします。ここでNodeについて話しているので Nodeについて話しているので、これらの操作は明らかに非同期です。 一時ファイルをいつ削除できるかを知るために、すべての操作が終了するのを待つには、どのような方法があるのでしょうか? 一時ファイルをいつ削除することができるかを知るために、すべての操作が終了するのを待つための慣用的な方法は何ですか?

以下は、私がやりたいことを示すいくつかのコードです。

do_something(tmp_file_name, function(err) {});
do_something_other(tmp_file_name, function(err) {});
fs.unlink(tmp_file_name);

しかし、このように書くと、3番目の呼び出しは、最初の2つの呼び出しがファイルを使う機会を得る前に実行される可能性があります。 がファイルを使用する機会を得る前に実行される可能性があります。最初の 2 つの呼び出しがすでに終了している (コールバックを呼び出した) ことを保証する何らかの方法が必要です。 の呼び出しがすでに終了している (コールバックを呼び出した) ことを保証する方法が必要です。 呼び出しを入れ子にすることなく (そして、実際にはそれらを同期させる)、次に進む前に最初の 2 つの呼び出しがすでに終了した (それらのコールバックを呼び出した) ことを保証する方法が必要です。

私は、コールバックでイベントエミッターを使用し、レシーバーとしてカウンターを登録することを考えました。 をレシーバーとして登録することを考えました。カウンターは終了したイベントを受信し、まだ保留中の操作がいくつあるかをカウントします。 をカウントする。最後の操作が終わると、そのファイルを削除する。 ファイルを削除する。しかし、レースコンディションのリスクがありますし、このようなことは通常行われないと思います。 通常、このようなことは行われません。

Nodeの人たちはこの種の問題をどのように解決しているのでしょうか?

どのように解決するのでしょうか?

更新しました。

今、私は見ていることをお勧めします。

  • 約束

    Promiseオブジェクトは遅延や非同期の計算のために使われます。 Promiseはまだ完了していないが、将来的に期待されている処理を表します。 将来的に期待される処理を表します。

    人気のあるプロミスライブラリは ブルーバード . を見てみることをお勧めします。 なぜ約束なのか .

    これを回すにはプロミスを使うべき。

    fs.readFile("file.json", function (err, val) {
        if (err) {
            console.error("unable to read file");
        }
        else {
            try {
                val = JSON.parse(val);
                console.log(val.success);
            }
            catch (e) {
                console.error("invalid json in file");
            }
        }
    });
    
    

    この中に

    fs.readFileAsync("file.json").then(JSON.parse).then(function (val) {
        console.log(val.success);
    })
    .catch(SyntaxError, function (e) {
        console.error("invalid json in file");
    })
    .catch(function (e) {
        console.error("unable to read file");
    });
    
    
  • ジェネレータです。 例えば co .

    nodejsとブラウザのためのジェネレータベースのコントロールフローです。 プロミスを使うことで、ノンブロッキングのコードをうまく書けるようになります。

    var co = require('co');
    
    co(function *(){
      // yield any promise
      var result = yield Promise.resolve(true);
    }).catch(onerror);
    
    co(function *(){
      // resolve multiple promises in parallel
      var a = Promise.resolve(1);
      var b = Promise.resolve(2);
      var c = Promise.resolve(3);
      var res = yield [a, b, c];
      console.log(res);
      // => [1, 2, 3]
    }).catch(onerror);
    
    // errors can be try/catched
    co(function *(){
      try {
        yield Promise.reject(new Error('boom'));
      } catch (err) {
        console.error(err.message); // "boom"
     }
    }).catch(onerror);
    
    function onerror(err) {
      // log any uncaught errors
      // co will not throw any errors you do not handle!!!
      // HANDLE ALL YOUR ERRORS!!!
      console.error(err.stack);
    }
    
    

もし私が正しく理解しているならば、非常に優れた 非同期 ライブラリを見てみるべきだと思います。特に シリーズ . githubページのスニペットからコピーしたものです。

async.series([
    function(callback){
        // do some stuff ...
        callback(null, 'one');
    },
    function(callback){
        // do some more stuff ...
        callback(null, 'two');
    },
],
// optional callback
function(err, results){
    // results is now equal to ['one', 'two']
});


// an example using an object instead of an array
async.series({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
        }, 200);
    },
    two: function(callback){
        setTimeout(function(){
            callback(null, 2);
        }, 100);
    },
},
function(err, results) {
    // results is now equals to: {one: 1, two: 2}
});

さらに、このライブラリはブラウザでも動作させることができます。