web-dev-qa-db-ja.com

node.jsの初心者ですが、イベントよりもコールバックを使用するとどのような利点がありますか?

私はJavaScriptの初心者であり、V8エンジンの内部で何が行われているのか実際には知りません。

そうは言っても、私はnode.js環境への早い段階での取り組みを本当に楽しんでいますが、notifier-observerに適合するようにプログラムを構造化できるようにグローバルイベントを発行する手段として、常にevents.EventEmitter()を使用していることがわかりましたObjective-CやPythonプログラムなど)と同じようなパターンを記述します。

私はいつも次のようなことをしています。

var events = require('events');

var eventCenter = new events.EventEmitter();

eventCenter.on('init', function() {
    var greeting = 'Hello World!';
    console.log('We're in the init function!);
    eventCenter.emit('secondFunction', greeting);
});

eventCenter.on('secondFunction', function(greeting) {
        console.log('We're in the second function!);
        console.log(greeting);
    eventCenter.emit('nextFunction');
});

eventCenter.on('nextFunction', function {
    /* do stuff */
});

eventCenter.emit('init');

つまり、実際には、「非同期」のnode.jsコードを期待どおりの順序で実行するコードに構造化しているだけで、意味がある場合は「逆方向のコーディング」を行っています。これをコールバックを多用した方法で実行する場合、パフォーマンス面でも哲学面でも違いはありますか?イベントの代わりにコールバックを使用して同じことをする方が良いですか?

24
Jog

コールバックの良い点は、そこにグローバル状態がないことであり、それらにパラメーターを渡すことは簡単です。関数download(URL, callback: (FileData)->void)がある場合、これは自己完結型の高階関数であり、基本的に「これを取得して実行する」関数を作成できます。他の誰もそのコールバックにハンドルを持たず、そのコールバックは親関数の指定されたパラメーター以外について何も知らないため、コードフローが期待どおりであることを確認できます。これにより、モジュール化され、テストが容易になります。

5つのファイルを並行してダウンロードしてさまざまなことを行う場合は、適切なコールバック関数を使用して、これらの関数のうち5つを起動するだけで済みます。匿名関数の構文が優れている言語では、これは非常に強力です。

一方、イベントは、_1..*_ユーザーに状態の変化を通知するように設計されています。 download(URL)の最後に「ダウンロード完了」イベントを発生させ、データの検索場所を認識しているprocessDownload()を起動する場合、実装をより多く結び付けています。状態の。現在、ダウンロードをどのように並列化していますか?さまざまなダウンロードをどのように異なる方法で処理しますか? download(URL, eventId)はエレガントですか? downloadAndDoThing(URL)はエレガントですか?ほとんどありません。

もちろん、すべてのものと同様に、あなたはトレードオフを行っています。ネストされたコールバックはコードの実行順序をより混乱させる可能性があり、簡単にグローバルにアクセスできないため、doプロデューサーとコンシューマー間の_1..*_関係。データの受け渡しに苦労することはありますが、追加の状態がないことで問題を回避できる場合は、とにかくメリットがあります。

とにかく。あなたはnode.jsでコーディングしていて、コールバックは慣用的であり、言語とライブラリはそれらの使用に合わせて設計されています。設計に利点があるかどうかにかかわらず、どの言語でも慣用的なコードを書くことでサポートが大幅に向上し、それを回避しようとするよりもはるかに簡単に生活できるようになることはほぼ間違いないと思います。

27
Phoshi

NodeJSでイベントを使用したことはありませんが、通常、クライアント側のJSイベントを使用するのは、何かが発生したことを通知することです。 AppointmentBookedEvent。SPAビューのさまざまな部分がそれに反応できるようにします(タイムラインでの表示、パネルへのロードなど)。
しかし、イベントを使用してメソッドが完了したことを通知することは、危険な道路になる可能性があります。イベントが発生したのと同じ順序でイベントを受信することはできないため、あらゆる種類のランダム性につながる可能性があります...
イベントの使用には何の問題もありませんが、特定のレベルの細分性があってはなりません。ドメインっぽいイベントに固執するなら、それでいい。ただし、メソッドが終了したことを通知することは細かすぎます。

2
Stefan Billiet

あなたが探求するかもしれない何かはそれらを放出しているオブジェクトの外のイベントの使用法です。あなたの例では、eventCenterは自身のイベントを発生させて処理するように見えます。他のオブジェクトがイベントの処理を開始した場合に、アプリケーションの構造がどのように変化するかを検討してください。

そのため、eventCenterは「init」を発行する可能性があり、他のオブジェクトはこれを処理して、スタートアップコードなどを実行できます。

0
Dan1701