0

私はこの記事を読んでいましたが、誰かが私に明らかにした場合、1つの特定の疑問があります.

http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb

var fs = require('fs')
  , sys = require('sys');

fs.readFile('treasure-chamber-report.txt', function(report) {
  sys.puts("oh, look at all my money: "+report);
});

fs.writeFile('letter-to-princess.txt', '...', function() {
  sys.puts("can't wait to hear back from her!");
});

コードは、ノードにファイルの読み取りと書き込みの 2 つのタスクを与え、その後スリープ状態になります。ノードがタスクを完了すると、そのコールバックが起動されます。ただし、同時に起動できるコールバックは 1 つだけです。そのコールバックの実行が完了するまで、他のすべてのコールバックは順番に待機する必要があります。それに加えて、コールバックが起動する順序についての保証はありません。

「では、同じデータ構造に同時にアクセスするコードについて心配する必要はありませんか?」 了解しました!これこそが、JavaScript のシングル スレッド/イベント ループ設計の全体的な美しさです!

  1. 上記の太字の行について誰か説明してもらえますか? 2 つの異なるプログラムがオブジェクトにアクセスしないことを心配できないのはなぜですか。
  2. 現在のスレッド化の方法に問題があるのはなぜですか?
  3. コールバックを起動する順序は問題になりますか? callBack A() が callBack b() の前に最初に戻るようにしましょう。
4

1 に答える 1

6

1) シングル スレッドで実行している場合は、マルチスレッド アプリケーションに伴う問題について心配する必要はありません。これには、同じオブジェクトを同時に使用しようとする 2 つの異なるスレッドが含まれます。たとえば、あるスレッドがハッシュからデータを読み取ろうとしているときに、別のスレッドが同じハッシュからデータを削除していたとします。キーと値のペアは、コードの 1 行に存在するように見えるかもしれませんが、次の行に到達するまでにスレッド化されているため、データが存在しない可能性があります。同様に、これらの問題を回避するために余分なコードや頭の痛い問題をすべて処理する必要はありません。

2) #1 を参照してください。トレードオフほどの問題ではありません。最近の多くのコンピュータには複数のプロセッサ/コアが搭載されているため、プログラムで一度に複数のスレッドを使用することは有益です。スレッドがブロックされていることが予想される場合にも役立ちます。たとえば、別のマルチスレッド言語では、ファイルの内容を読み取り、コールバックを追加せずに出力するのが一般的です。ただし、これは、ファイルの読み取り操作が完了するまで、スレッドが何もしない (ブロックされる) ことを意味します。マルチスレッド プログラミングを正しく行うことも非常に困難です。

3) 注文は保証されません。適切な順序を確保したい場合は、最初の呼び出しが返されるまで 2 番目の呼び出しの実行を待ちます。例えば

fs.readFile('treasure-chamber-report.txt', function(report) {
    sys.puts("oh, look at all my money: "+report);

    fs.writeFile('letter-to-princess.txt', '...', function() {
      sys.puts("can't wait to hear back from her!");
    });
});

これにより、一般に「コールバック地獄」と呼ばれるものに陥ることがあることに注意してください。

編集:コメントに対処するには:

1) NodeJS がファイルを読み取るのを「待機」している場合でも、NodeJS ではこれは非ブロック操作です。これは、ファイルが読み込まれる前であっても、メソッド呼び出し ( readFile) がすぐに戻ることを意味します。これは、データ IO 要求を基になるオペレーティング システムに渡すためです。オペレーティング システムには、そのような要求を処理するための独自のスレッドがあります。オペレーティング システムが読み取り (または書き込み) を完了すると、元のプロセスにデータの準備が整ったことを通知します。オペレーティング システムがこの作業を行っている間、NodeJS は 1 つのスレッドが待機している間、別の作業を続行させることができます。そのため、コールバックが必要です。最終的にデータを取得したときに次に何をすべきかを NodeJS に伝える方法が必要です。

2) 読みにくいこと以外に、コールバック地獄について本質的に悪いことは何もありません。実行しようとしている処理に複数の異なる非同期プロセス (ディスクへの読み取りと書き込みなど) が含まれている場合、次のような結果が得られると想像する人もいるかもしれません。

var doSomething function(){
    fs.readFile('step1.txt', function(result){
        // do something with the result
        fs.writeFile('step2.txt', function(){
            // okay, step2 is ready, so process that
            fs.readFile('step2.txt', function(result){
                fs.writeFile('step3.txt', function(){
                    //etc, etc
                });
            });
        });
    });
}

ネスティングが急速に深くなり、読みにくくなることがわかります。「JavaScript コールバック ヘル」を検索すると、このことについて話している議論がここや他の場所でたくさんあります。物事を平坦化する 1 つの方法は、インライン/匿名関数を避け、名前付き関数で平坦化することです。これにより、エディターでコールバックがそれほど深くネストされなくなります (ただし、ネストは字句の観点からはまだ発生しています)。

于 2012-11-13T17:14:23.833 に答える