9

Node.jsで遊んで、非同期I / Oとイベントプログラミングについてたくさん読んだ後、疑問符がいくつか残っています。

次の(擬似)コードについて考えてみます。

var http = require('http');

function onRequest(request, response)
{
    // some non-blocking db query
    query('SELECT name FROM users WHERE key=req.params['key']', function (err, results, fields) {
        if (err) {
            throw err;
        }
        username = results[0];
    });

    // some non-blocking db query
    query('SELECT name FROM events WHERE key=req.params['key']', function (err, results, fields) {
        if (err) {
            throw err;
        }
        event_name = results[0];
    });

    var body = renderView(username, event_name, template);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write(body);
    res.end();
};

http.createServer(onRequest).listen(8888);

// request A: http://127.0.0.1:1337/?key=A
// request B: http://127.0.0.1:1337/?key=B

(私は思う)イベントループの基本を理解している。libevを使用すると、Node.jsは一連のファイル記述子をポーリング(epoll / kqueue / ...)して、イベントがトリガーされたかどうか(新しい接続、書き込み可能、​​データが利用可能など)を確認するイベントループを作成します。新しいリクエストがある場合、イベントループはcreateServerに渡された無名関数を呼び出します。私が理解していないのは、その後に何が起こるかです。

1)クエリを同時に実行するには、dbドライバーに何らかのスレッド/接続プールが必要です。

2)1つのリクエストの範囲内:2つのクエリを送信するとどうなりますか?クエリがまだ返されていないため、renderViewを呼び出すことはできません。クエリが返されるのをどのように待ちますか?続行する前に、発生するまで保留中のコールバックのカウントを保持する必要がありますか?私が持っていた基本的な考えは次のとおりでした。

onRequest->非同期コードの実行->コールバックの待機->応答の作成。この場合の待機はブロックされるため、onRequestごとにスレッドを効果的に生成する必要があります。「応答を作成する前にコールバックが実行されるのを待つ」はどのように行われますか?

3)dbドライバーは、イベントループにそれが完了したことをどのように通知し、クエリ結果でコールバックを呼び出す必要がありますか?

4)イベントループは、onRequestイベントで作成した無名関数内でどのようにコールバックを実行しますか?これは、コールバック関数でコンテキストが「保存」されるクロージャの概念が登場する場所ですか?

4)dbの結果が得られたので、どのようにしてrenderView/res.write/res.endパーツの実行を継続しますか?

4

2 に答える 2

6

並列非同期コードパターンを実行します。

「両方の非同期関数からの結果を待つ」には、次の操作を実行できます。両方の非同期呼び出しで、コールバックは両方の結果を確認し、準備ができたらDoSomethingWithTwoDependantResultsを呼び出します。

あなたの例では、おそらくクエリを順番に実行する必要があります。

query(sql1, function(sqlres1) {
    query(sql2, function(sqlres2) {
        writeResultUsingDataFrom(sqlres1, sqlres2);
    }
});

2つのクエリを並行して実行するように変更された元のコード:

function writeReply(res, template, username, event_name)
{
    var body = renderView(username, event_name, template);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write(body);
    res.end();
} 

function onRequest(request, response)
{
    // some non-blocking db query
    query('SELECT name FROM users WHERE key=req.params['key']', function (err, results, fields) {
        if (err) {
            throw err;
        }
        username = results[0];
        if (username && event_name)
            writeReply(res, template, username, event_name);
    });

    // some non-blocking db query
    query('SELECT name FROM events WHERE key=req.params['key']', function (err, results, fields) {
        if (err) {
            throw err;
        }
        event_name = results[0];
        if (username && event_name)
            writeReply(res, template, username, event_name);

    });
};
于 2011-07-21T01:44:43.783 に答える
3

これを見たことがありますか?私はまだすべてのコツをつかんでいて、あなたの質問に詳細に答えることはできませんが、基本的にあなたはスレッドプールについて正しいです...ライアンはビデオでかなり多くを説明します。

編集:そしてこれは彼がより詳細に入る約1年後からのものです。

于 2011-07-20T21:09:22.720 に答える