21

非同期性に関する基本的なことを理解しています。物事は順番に実行されません。そして、それには非常に強力な何かがあることを理解しています... 伝えられるところでは. しかし、私の人生では、コードに頭を悩ませることはできません。私が書いた非同期Node.JSコードを見てみましょう...しかし、本当に理解していません。

function newuser(response, postData) {
    console.log("Request handler 'newuser' was called.");
    var body = '<html>' + 
        '<head>' +
        '<meta http-equiv="Content-Type" content="text/html; ' +
        'charset=UTF-8" />' +
        '</head>' +
        '<body>' +
        '<form action=" /thanks" method="post">' +
        '<h1> First Name </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<h1> Last Name </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<h1> Email </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<input type="submit" value="Submit text" />' +
        '</body>' +
        '</html>';
    response.writeHead(200, { "Content-Type": "text/html" });
    response.write(body);
    response.end();
}

再び反応はどこから来たのですか?ポストデータ? この「コールバック」で変数を定義して、それをコールバックの外で使用できないのはなぜですか? プログラムの残りの部分を非同期にして、いくつかのものを順次にする方法はありますか?

4

3 に答える 3

45

この関数がどこで使用されているかはわかりませんが、コールバックのポイントは、非同期で実行される関数にコールバックを渡すことです。コールバックを保存し、その関数が必要な処理を完了すると、必要なパラメーターを使用してコールバックを呼び出します。前後の例がおそらく最適です。

フレームワークがあり、データベースからデータを取得するために長時間実行される操作があるとします。

function getStuffFromDatabase() {
  // this takes a long time
};

同期的に実行したくないので、ユーザーがコールバックを渡すことを許可します。

function getStuffFromDatabase(callback) {
  // this takes a long time
};

への呼び出しで長い時間がかかることをシミュレートしsetTimeoutます。また、データベースからデータを取得したふりをしますが、文字列値をハードコードするだけです。

function getStuffFromDatabase(callback) {
  setTimeout(function() {
    var results = "database data";
  }, 5000);
};

最後に、データを取得したら、フレームワークの関数のユーザーから提供されたコールバックを呼び出します。

function getStuffFromDatabase(callback) {
  setTimeout(function() {
    var results = "database data";
    callback(results);
  }, 5000);
};

フレームワークのユーザーとして、関数を使用するには次のようにします。

getStuffFromDatabase(function(data) {
  console.log("The database data is " + data);
});

したがって、ご覧のとおり(例とdata同じ)、コールバック;に渡す関数から来ました。そのデータが何であるかを知っているときに、そのデータを提供します。responsepostData

コールバックに値を設定して、それをコールバックの外で使用できない理由は、コールバック自体が後で発生するまで発生しないためです。

//  executed immediately  executed sometime in the future
//      |                  |       by getStuffFromDatabase
//      v                  v
getStuffFromDatabase(function(data) {
  var results = data; // <- this isn't available until sometime in the future!
});

console.log(results); // <- executed immediately

実行するconsole.logと、課題はvar resultsまだ発生していません。

于 2012-06-27T19:48:03.380 に答える
8

ここにいくつかの無関係な質問があります:

1)非同期の力は、メインスレッドをロックすることなく同時に複数のことを実行できることです。一般的なノードとjsでは、これは特にajaxファイルリクエストに当てはまります。これは、ファイルを取得するためにいくつかの非同期呼び出しを起動でき、コンテンツのレンダリング中にメインスレッドをロックしないことを意味します。私が好むフレームワークはjQueryです。これには、jQueryを使用するための非同期呼び出しをラップして標準化する便利な$.Deferredがあります。

2)responseとpostDataは親メソッドから取得されます。ここには魔法のようなものは何もありません。これは通常の関数呼び出しであるため、これらの値は他の場所で作成され、この呼び出しに渡されます。使用しているノードフレームワークに応じて、メソッドの正確なシグネチャが変わります。

3)スコープが適切であれば、コールバックでグローバル変数を定義できます。スコープが何であるかを学ぶのに助けが必要なようですが。ここにいくつかのリンクがあります

http://www.digital-web.com/articles/scope_in_javascript/

http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/

4)非同期に移行すると、元に戻すことはできませんが、jQuery Deferredsのようにpromiseと遅延オブジェクトを利用することで、いくつかの非同期が完了するのを待ってから、さらに別の非同期で実行を続行できます。延期はあなたの友達です。

http://api.jquery.com/category/deferred-object/

于 2012-06-27T19:51:59.290 に答える
2

Node Beginner Bookを読んでいるようです。この本全体を読むことをお勧めします。これは本当に優れた入門書です。Javascript をよりよく理解しようとしている場合は、YouTube にある Douglas Crockford のビデオが優れた概要です: 1 , 2 .

あなたが投稿したコードには、私が本当にあなたを助けるのに十分なコンテキストがありません. responseは関数に渡すパラメーターであり、postData からのものではありません。Node Beginner Book が示唆する方法でコードを操作している場合、おそらく、Node.js に付属する http モジュールの一部である createServer 関数からずっと newuser 関数に応答を渡していることになります。

Javascript はレキシカル スコープであるため、コールバックで変数を定義してコールバックで使用することはできません。これは、 Javascriptのスコープのトピックに関するスタック オーバーフローの投稿です。私が投稿した Doug Crockford による最初のビデオにも、Javascript のスコープ規則に関する優れた説明があります。

Javascript は必ずしも非同期ではありません。これは、非同期ロジックを簡単に実装するための便利なツールであるクロージャーである無名関数を提供するだけです。繰り返しになりますが、Node Beginner Book は、Node を使用して同期コードを記述し (必要なものではありません)、それを書き直して非同期にする良い例を示しています。

于 2012-06-27T19:57:54.560 に答える