web-dev-qa-db-ja.com

同期プログラミングと非同期プログラミングの違いは何ですか(node.js内)

私は nodebeginner を読んでいますそして私は次の2つのコードに出会いました。

最初の1つ:

    var result = database.query("SELECT * FROM hugetable");
    console.log("Hello World");

2番目のもの:

    database.query("SELECT * FROM hugetable", function(rows) {
       var result = rows;
    });
    console.log("Hello World");

私は彼らがするべきことを手に入れました、彼らは質問に対する答えを検索するためにデータベースに質問します。そしてconsole.log('Hello world')

最初のものはおそらく同期コードです。そして2番目のものは非同期コードです。

2つの部分の違いは私にとって非常に曖昧です。出力はどうなりますか?

非同期プログラミングに関するグーグルは私にとっても役に立ちませんでした。

175
Azeirah

違いは、最初の例では、プログラムが最初の行でブロックされることです。次の行(console.log)は待つ必要があります。

2番目の例では、クエリの処理中にconsole.logが実行されます。つまり、あなたのプログラムが他のことをしている間、問い合わせはバックグラウンドで処理され、そして問い合わせデータが準備できたら、あなたはそれを使ってあなたが望む何でもするでしょう。

つまり、簡単に言うと、最初の例ではブロックされ、2番目の例ではブロックされません。

次の2つの例の出力

// Example 1 - Synchronous (blocks)
var result = database.query("SELECT * FROM hugetable");
console.log("Query finished");
console.log("Next line");


// Example 2 - Asynchronous (doesn't block) 
database.query("SELECT * FROM hugetable", function(result) {
    console.log("Query finished");
});
console.log("Next line");

だろう:

  1. Query finished
    Next line
  2. Next line
    Query finished


Node自体はシングルスレッドですが、並列実行できるタスクがいくつかあります。たとえば、ファイルシステム操作は別のプロセスで行われます。

これが、Nodeが非同期操作を実行できる理由です。1つのスレッドがファイルシステム操作を実行しているのに対して、メインのNodeスレッドはJavaScriptコードを実行し続けます。 Nodeのようなイベント駆動型サーバーでは、ファイルシステムスレッドはメインノードスレッドに、そのイベントに関連するデータ(データベースクエリやエラーの結果など)とともに、完了、失敗、進行などの特定のイベントを通知しますメインノードスレッドがそのデータの処理方法を決定します。

これについてもっと読むことができます: シングルスレッドノンブロッキングIOモデルがNode.jsでどのように動作するか

205
Salvatorelab

これら2つの方法の違いは次のとおりです。

同期的な方法:各操作が完了するのを待ってから、次の操作を実行します。クエリの場合:console.log()コマンドは、クエリがデータベースからすべての結果を取得するために実行を終了しない限り&まで実行されません。

Asynchronous way:各操作が完了するのを待つのではなく、最初のGOですべての操作を実行します。結果が利用可能になると、各操作の結果が処理されます。あなたの質問のために:console.log()コマンドはDatabase.Query()メソッドの直後に実行されます。データベースクエリがバックグラウンドで実行され、データの取得が終了したら結果を読み込みます。

ユースケース

  1. あなたの操作がDBからの巨大なデータの問い合わせのように非常に重い作業をしていないのであれば、同期的な方法、そうでなければ非同期的な方法を進めてください。

  2. バックグラウンドであなたがあなたの重い仕事を続けることができる間、非同期の方法であなたはいくらかの進歩指標をユーザーに示すことができます。これはGUIアプリにとって理想的なシナリオです。

69
Santosh Panda

両方の例に一行追加すると、これはもう少し明確になります。

var result = database.query("SELECT * FROM hugetable");
console.log(result.length);
console.log("Hello World");

2番目のもの:

database.query("SELECT * FROM hugetable", function(rows) {
   var result = rows;
   console.log(result.length);
});
console.log("Hello World");

これらを実行してみると、最初の(同期的な)例であるresult.lengthが 'Hello World'行の前に出力されることに気付くでしょう。 2番目(非同期)の例では、result.lengthは(おそらく) "Hello World"行の後に表示されます。

これは、2番目の例では、database.queryがバックグラウンドで非同期に実行され、スクリプトが「Hello World」でそのまま続行されるためです。 console.log(result.length)は、データベースクエリが完了したときにのみ実行されます。

22
Martijn

第一に、私はこの質問に答えるのが遅れていることを実感します。

同期と非同期について説明する前に、プログラムの実行方法を簡単に見てみましょう。

同期の場合、各ステートメントは次のステートメントが実行される前に完了します。この場合、プログラムは文の順序どおりに評価されます。

これがJavaScriptでの非同期のしくみです。 JavaScriptエンジンには2つの部分があります。1つはコードを調べて操作をエンキューし、もう1つはキューを処理します。キュー処理は1つのスレッドで行われるため、一度に1つの操作しか実行できません。

非同期操作(2番目のデータベースクエリなど)が見られると、コードが解析されて操作がキューに入れられますが、この場合、この操作が完了するとコールバックが実行されるように登録されます。キューには既に多くの操作があります。キューの先頭にある操作が処理され、キューから削除されます。データベースクエリの操作が処理されると、要求がデータベースに送信され、完了時にコールバックが完了時に実行されます。この時点で、操作を「処理」したキュープロセッサは、次の操作に移動します。この場合

    console.log("Hello World"); 

データベース照会はまだ処理中ですが、console.log操作はキューの先頭にあり、処理されます。これは同期操作であるため、すぐに実行され、すぐに "Hello World"という出力が得られます。しばらくしてデータベース操作が完了し、その後クエリに登録されたコールバックが呼び出されて処理され、変数resultの値がrowsに設定されます。

ある非同期操作が別の非同期操作になる可能性があります。この2番目の操作はキューに入れられ、キューの先頭に来ると処理されます。非同期操作で登録されたコールバックを呼び出すと、JavaScriptの実行時に操作の結果が返されます。

どのJavaScript操作が非同期であるかを知る簡単な方法は、それがコールバックを必要とするかどうかに注意することです - コールバックは最初の操作が完了したときに実行されるコードです。問題になっている2つの例では、2番目のケースだけがコールバックを持っていることがわかります。したがって、これは2つの非同期操作です。非同期操作の結果を処理するスタイルが異なるため、必ずしもそうとは限りません。

もっと学ぶために、約束について読んでください。約束は、非同期操作の結果を処理できるもう1つの方法です。約束についてのいいところは、コーディングスタイルが同期コードに近いということです。

ノード 'fs'のような多くのライブラリは、いくつかの操作に対して同期スタイルと非同期スタイルの両方を提供します。設定ファイルを読み込む場合のように、操作に時間がかからず、あまり使われない場合は、同期スタイルの操作の方が読みやすいコードになります。

18
Jay

同期の場合、console.logコマンドはSQLクエリの実行が終了するまで実行されません。

非同期の場合は、console.logコマンドが直接実行されます。その後、クエリの結果は "callback"関数によって後で保存されます。

5
related

主な違いは非同期プログラミングです。それ以外の場合は実行を停止しません。 「要求」が行われている間、他のコードの実行を続けることができます。

4
thebreiflabb

この関数は2番目の関数を非同期にします。

最初のものは、次の行が続くことができる前にプログラムが各行がそれが走るのを終えるのを待つことを強制します。 2番目のものは各行が同時に(そして独立して)走ることを可能にします。

非同期または並行性を可能にする言語およびフレームワーク(js、node.js)は、リアルタイム伝送を必要とするもの(チャット、ストックアプリケーションなど)に最適です。

2
Anton Chan

同期プログラミング

C、C#、Javaなどのプログラミング言語は同期プログラミングであり、これまでに書いたものは、書いた順に実行されます。

-GET DATA FROM SQL.
//Suppose fetching data take 500 msec

-PERFORM SOME OTHER FUNCTION.
//Performing some function other will take 100 msec, but execution of other 
//task start only when fetching of sql data done (i.e some other function 
//can execute only after first in process job finishes).

-TOTAL TIME OF EXECUTION IS ALWAYS GREATER THAN (500 + 100 + processing time) 
msec

非同期

NodeJsは非同期機能を思い付きます、それは本質的にノンブロッキングです。キュー内の次のタスクの実行を開始し、その時間がかかるタスクが完了するたびに、コールバックを使用して通知します。次の例が役立ちます。

//Nodejs uses callback pattern to describe functions.
//Please read callback pattern to understand this example

//Suppose following function (I/O involved) took 500 msec
function timeConsumingFunction(params, callback){
  //GET DATA FROM SQL
  getDataFromSql(params, function(error, results){
    if(error){
      callback(error);
    }
    else{
      callback(null, results);
    }
  })
}

//Suppose following function is non-blocking and took 100 msec
function someOtherTask(){
  //some other task
  console.log('Some Task 1');
  console.log('Some Task 2');
}

console.log('Execution Start');

//Start With this function
timeConsumingFunction(params, function(error, results){
    if(error){
      console.log('Error')
    }
    else{
      console.log('Successfull'); 
    }
  })

//As (suppose) timeConsumingFunction took 500 msec, 
//As NodeJs is non-blocking, rather than remain idle for 500 msec, it will start 
//execute following function immediately
someOtherTask();

つまり、出力は次のようになります。

Execution Start
//Roughly after 105 msec (5 msec it'll take in processing)
Some Task 1
Some Task 2
//Roughly After 510 msec
Error/Successful //depends on success and failure of DB function execution

同期が確実に600(500 + 100 +処理時間)ミリ秒以上かかる場合の違いは明らかです、非同期は時間を節約します

0
Neeraj Bansal