14

私はこのように見えるモジュールをたくさん書いています:

function get(index, callback) {
    if (cache[index] === null) {
        request(index, callback); // Queries database to get data.
    } else {
        callback(cache[index]);
    }
}

注:これは私の実際のコードを少し簡略化したものです。

そのコールバックは、同じ実行で呼び出されるか、しばらくしてから呼び出されます。これは、モジュールのユーザーが最初に実行されるコードがわからないことを意味します。

私の観察では、そのようなモジュールは、以前はJavaScriptエンジンによって解決されていたマルチスレッドのいくつかの問題を再導入します。

質問:process.nextTickモジュールの外部でコールバックが呼び出されても安全であるかどうかを確認する必要がありますか?

4

2 に答える 2

12

これは、コールバック関数で何をするかに完全に依存します。get戻ったときにコールバックがまだ発生していないことを確認する必要がある場合は、process.nextTickフローが必要になります。多くの場合、コールバックがいつ発生するかは気にしないため、コールバックの実行を遅らせる必要はありません。すべての状況に当てはまる決定的な答えを出すことは不可能です。コールバックを常に次のティックに延期するのは安全なはずですが、その方法ではおそらく少し効率が悪くなるため、トレードオフになります。

次のティックのコールバックを延期する必要があると私が考えることができる唯一の状況は、への呼び出しのget、への呼び出しの前に実際に何かを設定する必要がある場合ですcallback。これはおそらくまれな状況であり、実際の制御フローを改善する必要があることも示している可能性があります。コールバックが正確に呼び出されたときにまったく依存しないようにする必要があります。そのため、コールバックが使用する環境は、get呼び出された時点ですでに設定されている必要があります。

(コールバックベースではなく)イベントベースの制御フローには、実際のイベントの発生を延期する必要がある場合があります。例えば:

function doSomething() {
    var emitter = new EventEmitter();
    cached = findCachedResultSomehow();
    if (cached) {
        process.nextTick(function() {
            emitter.emit('done', cached);
        });
    } else {
        asyncGetResult(function(result) {
            emitter.emit('done', result);
        });
    }
    return emitter;
}

この場合、キャッシュされた値の場合は発行を延期する必要doSomethingあります。そうしないと、の呼び出し元がリスナーをアタッチする前にイベントが発行されるためです。コールバックを使用する場合、通常、この考慮事項はありません。

于 2012-10-26T10:31:37.350 に答える
8

http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony

内部でコールバックを実行している場合は、適切な方を実行してください

他の人が使用するモジュールを作成する場合、非同期コールバックは常に非同期である必要があります。

于 2013-12-10T13:09:51.887 に答える