2016-05-21 13 views
1

私はこの投稿を見ました:https://www.codementor.io/nodejs/tutorial/manage-async-nodejs-callback-example-code、コードを実行した後、私はnodejsが非同期であることを確認します。 しかし、nodejのasyncus機能をもう一度テストするために2つのjsファイルを作成しました。Nodejsは実際に非同期ですか?

ファイル1:callback_example.js

exports.countless = function(callback){ 
    var date = new Date(); 
    console.log("*" + date.getSeconds()); 
    var x = 0; 
    for(var i = 1; i <= 1000000000; i++){ 
     x++; 
    } 
    callback(x); 
    date = new Date(); 
    console.log("**" + date.getSeconds()); 
} 

exports.check = function(callback){ 
    var date = new Date(); 
    console.log(date.getSeconds()); 
    callback(123); 
    date = new Date(); 
    console.log(date.getSeconds()); 
} 

ファイル2:call.js

var call = require('./callback_example'); 

call.countless(function(x){ 
    console.log(x); 
}); 

call.check(function(x){ 
    console.log(x); 
}); 

そして、私はnode callとして、端末にcall.jsを実行すると、私は見たことcountless()が終了した後、check()を実行してを実行します。つまり、nodejsはsynchronusですか?なぜですか?誰も私がそれに答えるのを助けることができる?どうもありがとうございました!

+0

「nodejsは非同期です」*という文が広すぎますが、確かに非同期操作を使用することができます – charlietfl

答えて

2

node.jsはV8 Javascriptエンジンを使用し、Javascriptの同期行を順番に実行します。質問の中でcountlesscheckの両方のメソッドのようなシーケンシャルなコーディングステートメントを書くと、他のプログラミング言語のように同期的に実行されます。

https://nodejs.org/en/のnode.jsの説明の一部です。

Node.jsのは、それが 軽量かつ効率的になり、イベント駆動型、非ブロックI/Oモデルを使用しています。

これは、node.jsが非同期であると言うよりも、実際にはそれがうまくいくと説明しています。

ネットワーキングなどの外部インターフェイスを使用する実際の非同期操作は、実際にはnode.jsではブロックされません。その場合、非ブロッキング関数を呼び出すと操作が開始され、Javascriptの次の行でJavascriptの実行が継続されます。ノンブロッキング操作が将来完了すると、イベントがイベントキューに挿入され、V8エンジンが現在の実行スレッドの実行を終了すると、そのイベントをイベントキューから取得し、コールバックを呼び出します。

真の非同期操作は、純粋なJavascriptでゼロから(実際のコードがバックグラウンドで実行される)書き込むことはできません。実際の非同期操作を作成するには、外部インターフェイス(ネットワーキング、ファイルI/Oなど)からの助けが必要です。タイマーでシミュレーションすることはできますが、実際にはバックグラウンドで実行されるものはないため、実際には非同期ではありません。タイマーは、実際に実行されるタイミングをずらすだけです(実際にはJavaScriptの実行と並行して動作するわけではありません)。ここで

は、Node.jsの非同期操作の例です:

var fs = require('fs'); 

console.log("one"); 
fs.readFile('temp.txt', function(err, data) { 
    if (err) { 
     console.log(err); 
    } else { 
     console.log("got data"); 
    } 
}); 
console.log("two"); 

これは、次のような出力を生成します。

one 
two 
got data 

fs.readFile()操作は、実際には非同期です。あなたがそれを呼び出した後、それはバックグラウンドでその仕事をしますが、その後のステートメントのあなたのJavascriptの残りは実行を続けます。それが完了すると、いつか将来、エラーまたはデータでコールバックと呼ばれます。

+1

"本当に"非同期ではないことにあなたの注意が紛らわしいと思います。すべての意図と目的のために、約束事と 'setTimeout'は、「将来のある時点で」完了するという点で、非同期です。 –

+1

@DanPantry - しかし、バックグラウンドでは何も実行しないので、 'setTimeout()'はコードのタイミングをシフトします。私はそれを重要かつ適切な違いに気付くように私の答えに入れました。 'fs.readFile()'は実際の作業を非同期でバックグラウンドで行います。 'setTimeout(fn、1000)'はバックグラウンドで実際の仕事をしません。関数が呼び出されるタイミングをシフトします。 – jfriend00

+0

@toilanvd - これはあなたの質問に答えましたか?その場合は、回答の左側にある緑色のチェックマークをクリックしてコミュニティに知らせ、スタックのオーバーフローに関する適切な手順に従うための評価ポイントを獲得してください。 – jfriend00

1

ノード自体は非同期ではなく、イベントループを主要な構成として使用します。イベントループの反復は、他のプログラミング言語と同様に、同期して実行されます。

ここの例では、非同期コードはまったく使用していません。ちょうど何かがコールバックの中にあるからといって必ずしもそれが非同期であるとは限りません(そうでなければmapは非同期です)。ここでは高次関数を単純に採用しています。

これらの両方を個別に入れてみてください。setTimeout s;呼び出し順序は保証されません。

ノード保証実行を完了するので、任意の同期コードは、それが書かれている順序で実行される(すなわち、それはthrows最初returnステートメントまでない限り、任意の機能が完全に実行される、である)、 - ちょうど他の不可欠のよう言語。ただし、I/O操作やPromiseを使用するようなものは、タスクキューにコールバックを追加して将来のある時点で実行されるため、実行順序が保証されません。

NodeJSはシングルスレッドであり、大きな数字のforループは、CPUバインドされた操作としてその単一スレッドを食いつぶすので、アプリケーション全体をハングアップするような計算量の重い処理を行う場合は注意が必要です。計算量の重い作業のためには、他の言語で書かれた子プロセスを使用することができます(child_processモジュールを使用)。

3

call.countless()を呼び出すと、その関数が実行されていますが、その内部にI/Oをブロックするものはありません。したがって、ランタイムはforループ操作で忙しいです。もしあなたがBlocking I/O操作を書いていたら、NODE JSの非同期性を知っていたでしょう。

例えば、I/O操作をブロック:forループファイル読み取り/書き込み、タイムアウト、DB操作、Ajax呼び出しの後

は通訳が第二の機能に行く完了する。

+0

私はあなたがノンブロッキングI/Oを意味すると思います。 I/OをブロックすることはNodeにとって非常に悪いことです。 –

+0

それは美しさがあるところです上記のようにI/Oをブロックしているので、V8エンジンはこれをイベントループに入れます。したがって、ノードシングルスレッドはこれらのブロック入出力から解放され、他の操作を続行します@DanPantry –

+0

Uh ...いいえ、I/Oをまったくブロックしていません。定義によるI/Oのブロックは、I/O操作が完了するまで現在アクティブなスレッドが停止する場合です。 Nodeはこれをデフォルトでは行いません(ただし、 'module.xxxxSync'操作で行うことができます)。標準ライブラリのすべてのノードI/O関数は、これらのバリアントを使用しない限り、ブロックされません。 V8はそれが主張しているほど魔法ではありません。 –

関連する問題