2012-06-27 10 views
18

私は非同期性に関する基本的なことを理解しています。そして、それについては非常に強力なものがあるとわかっています...しかし、私の人生のために、私はコードの周りに私の頭を包むことはできません。私が書いた非同期Node.JSコードを見てみましょう...しかし、実際には得られません。Laymanの用語での非同期コードの理解

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(); 
} 

応答はどこから戻ってきましたか? postData?なぜ私はこの "コールバック"で変数を定義し、それをコールバックの外で使用できないのですか?いくつかの事柄をシーケンシャルにしてから、プログラムの残りの部分を非同期にする方法はありますか?

答えて

41

私はこの関数がどこで使用されているのかは分かりませんが、コールバックのポイントは非同期に実行される関数にそれらを渡すことです。あなたのコールバックを保存しておき、その機能が必要なときに完了したら、コールバックに必要なパラメータを設定します。フロントツーバックの例がおそらく最も良いでしょう。

私たちにはフレームワークがあり、その中には長い時間実行される操作があり、データベースからいくつかのデータを取得しているとします。

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); 
}; 

最後に、一度私たちはデータを持って、私たちよコールフレームワークの機能の利用者が私たちに与えられたコールバック。あなたは(あなたの例ではresponseと同じとpostDatadataを見ることができるよう、だから、

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

:フレームワークのユーザーとして

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

は、あなたが機能を使用するには、このような何かをしたいですあなたがコールバック に渡すという関数から来ました。そのデータが何であるべきかを知っているときにそのデータをあなたに提供します。

コールバックに値を設定してコールバック以外で使用できない理由は、コールバック自体が後で実行されないためです。 console.logの実行は、var resultsの割り当てはまだ起きていない

// 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 

+0

技術的な点からは、あなたは間違っていましたが、なぜ「最初にコールバックをしたいのですか」と尋ねました。これが非同期を重要なものにする理由です。 – jcolebrand

+3

私は今この2〜3回は読んでいないとは言わないでしょうが、それは物理的にここにいなければ、おそらく最良の説明です。 – PinkElephantsOnParade

+1

これはコールバックの仕組みを理解するための素晴らしい説明だと思います。ありがとう! – wmock

6

あなたはここで、いくつかの無関係な質問があります。

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

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のDeferredと同様繰延オブジェクトを活用することで、あなたはにはいくつかのasyncsを待つことができますさらに別の非同期で実行を続行する前に完了してください。遅れはあなたの友人です。

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

+0

何とか私の最初の見てこの非常に良い答えを逃した:+1 – PinkElephantsOnParade

+0

まあまあでした。私ってば最高! –

+2

私はあなたの自信に拍手を送る – PinkElephantsOnParade

1

あなたはNode Beginner Bookて作業しているように見えます。私はあなたが本全体を通して作業することをお勧めします。本当に素晴らしい紹介です。 Javascriptをよりよく理解しようと思っている場合は、YouTubeのDouglas Crockfordの動画は素晴らしい概観です:12

あなたが投稿したコードには、本当に助けになる文脈がありません。 responseはあなたの関数に渡すパラメータであり、postDataからのものではありません。 Node Beginner Bookが示唆しているようにコードを使って作業しているのであれば、Nodeに付属しているhttpモジュールの一部であるcreateServer関数からnewuser関数への応答を返すでしょう。

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

JavaScriptは必ずしも非同期である必要はありません。クロージャである匿名関数を提供するだけで、簡単に非同期ロジックを実装するのに便利なツールです。ここでもNode Beginner Bookは、ノードで同期コードを書いて、それを非同期にするための書き換えのよい例を示しています。

関連する問題