- ベストアンサー
Ajaxの非同期通信について
- Ajaxを使用した非同期通信について質問があります。
- 特定の部分が理解できません。自分で作った変数resultに、通信に成功した場合にサーバ側のPHPが生成したDOM要素を代入するのですか?
- また、loadstartとloadの違いや、ajaxとブラウザ上でのDOM生成の違いについても教えてください。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> サーバサイドで完全にhtmlを作る場合は、ページすべてのphpファイルでないといけ ないのですね。 > 一部分だけphpにしてhtmファイルにインクルードするかたちではだめなのですね。 ちょっと勘違いがあるようです。 サーバー側でHTMLを作る手法は、様々あります。 ・HTML文書内に可変部だけPHPプログラムでコーディングするという方法は一般的ですし、 ・静的HTMLから別のPHPをSSIで読み込む(exec やinclude)という方法もありますし、 ・PHPから静的HTMLを雛形として読み込んで一部を書き換えてからブラウザに出力するという方法も可能で、 いろいろです。 ですが、 いまは、サーバーサイドでどんな仕組みでHTMLを生成するのかは、 本題ではありません。 肝心なのは、 ・formのsubmitやリンクボタンでページを移動するのなら、 サーバーからフルのHTML生成をもらう必要があり、 この場合は画面遷移することになる ・JavaScriptでDOMを使って動的に画面を変更するのであれば、 サーバー側の処理が必要であっても画面遷移しなくてすむ(ダイナミックHTML) のが違うという点です。 この違いが理解できていれば、「DOMとはなにか?」や 「”サーバーサイドでDOMを生成する”というのは用語が違う。サーバーサイドで生成するのは、DOMそのものではなくて、DOMに入れる値のところまで”」についての疑問も解消できるはずです。 > 地図の場合はなぜクライアントだけのDOM生成ではできないのでしょうか? 前にも説明しましたが、世界中の詳細な地図データというのは、データが大きするからです。 もし、クライアントだけで画面遷移なしに世界のどこにでも移動できる地図アプリを作ろうとすれば 世界中の詳細な地図データを あらかじめクライアントがもっておかねばなりません。 (カーナビでのDVDやHDDに入っている地図データがこの方式ですね)(日本だけのデータですが) Ajaxなしで、DOMだけでこれをやるとなると、最新の世界の詳細地図データが サーバーからクライアントに送信完了するまで地図アプリが利用できないことになり 現実的な待ち時間ではなくなります。 それよりも、地図がスクロールされたときに、その前後の表示に必要な小さな地図データのみをサーバーからクライアントに送るようにすれば サーバーもクライアントもデータ負荷が小さくなります。 > ajaxはサーバサイドで作った要素をサーバから受け取り、 > ページ遷移をせずに一部分だけ変更するjsの技術という事ですね。 > PHPだけでの場合はページ遷移をしないと絶対にいけないというのが、 > ajaxとの決定的な違いですね。 > index.phpなどサーバサイドでページすべてを作成してページ遷移するタイプ、 > ページ遷移するがajaxとただのDOM生成はページ遷移しないと分けて考えます。 はい。その理解でよろしいかと。
その他の回答 (4)
- superside0
- ベストアンサー率64% (461/711)
No4で 補足質問された件は、 すべて、その考え方で問題ないと思います。
- superside0
- ベストアンサー率64% (461/711)
> ajaxの場合は必ず値だけサーバサイドで作って、 > その値をサーバからもらったJSがDOM生成するのでしょうか? はい、その通りです。 AJAXとはなにかということと、それのサーバーやクライアントでの役割分担を 整理して考えてはどうでしょう。 (1)画面1→[formのsubmit]→画面2 のような画面推移をする単純なCGI (2)画面A →ボタン等の操作→画面AのままでHTMLが動的に変更 (3)画面A→ボタン等の操作→画面Aのままで サーバーへの問い合わせ結果でHTMLが動的に変更 という3種類の Webアプリがあったとします。 (1)の場合は、 画面1のsubmitボタンで、サーバーにFORMデータが送信されて、 サーバーはそのGET/POSTデータに合わせて画面2のフルのHTMLを作ります。 (この場合、DOMというJavaScriptのAPIを使うことはありません) (2)の場合は 画面Aのままで、ボタン等の操作をJavaScriptが感知したうえで DOM というAPIを使って、画面AのHTMLを動的に変更します。 この場合、画面Aを表示中にサーバーとのやりとりはありませんので JavaScript内に表示の切り替えの判断に使う アルゴリズムやデータは あらかじめブラウザに送っておく必要があります。 しかし、これだと、 地図データのように、データが非常に大きいのに使うのは一部という場合や チャットのように他のクライアントの発言をリアルタイムに自分の画面に反映したい場合は、 対応できません。 そこで(3)のAJAXという手法を使います。 この場合は、画面推移なしに動的にHTMLを変更したいのが目的なのですから サーバーからは”更新部分のみ”のデータをもらって それをパースしたあとで、JavaScriptのDOMというAPIを使って 現在表示中のHTMLの該当部分を動的に変更することになります。 そうでなく サーバーで更新後のフルのHTMLを作りなおして、 画面推移させてしまったのでは 前述の(1)のような普通のCGIになってしまうので、AJAXとは呼びません。 > もしかして、ページ遷移なしで一部の要素だけを変更する作業はフロントjsでしかで きず、 >サーバサイドではできないのでしょうか? その通りです。 AJAXでは更新部分のデータは、サーバーサイドで作っていますが それを表示画面に反映させるというダイナミックHTMLの処理は、 JavaScript等のクライアントサイドスクリプトの仕事です。 > ajaxを使わずにphpで動的に要素を作った場合は、htmlタグをphpが作 って、 > ブラウザに渡すので、要素自体を作成しているのですね。 そうです。 画面を動的に更新する場所が一切なく、PHPでHTMLをいちから生成し直して、 画面推移させてるだけのWebアプリの場合は DOMというAPIは使っていません。
お礼
>>> (1)の場合は、 画面1のsubmitボタンで、サーバーにFORMデータが送信されて、 サーバーはそのGET/POSTデータに合わせて画面2のフルのHTMLを作ります。 (この場合、DOMというJavaScriptのAPIを使うことはありません) サーバサイドで完全にhtmlを作る場合は、ページすべてのphpファイルでないといけないのですね。 一部分だけphpにしてhtmファイルにインクルードするかたちではだめなのですね。 下記もこれにがいとうしますね。 >>> > ajaxを使わずにphpで動的に要素を作った場合は、htmlタグをphpが作 って、 > ブラウザに渡すので、要素自体を作成しているのですね。 そうです。 画面を動的に更新する場所が一切なく、PHPでHTMLをいちから生成し直して、 画面推移させてるだけのWebアプリの場合は DOMというAPIは使っていません。 >>> しかし、これだと、 地図データのように、データが非常に大きいのに使うのは一部という場合や チャットのように他のクライアントの発言をリアルタイムに自分の画面に反映したい場合は、 対応できません。 そこで(3)のAJAXという手法を使います。 この場合は、画面推移なしに動的にHTMLを変更したいのが目的なのですから サーバーからは”更新部分のみ”のデータをもらって それをパースしたあとで、JavaScriptのDOMというAPIを使って 現在表示中のHTMLの該当部分を動的に変更することになります。 そうでなく サーバーで更新後のフルのHTMLを作りなおして、 画面推移させてしまったのでは 前述の(1)のような普通のCGIになってしまうので、AJAXとは呼びません。 地図の場合はなぜクライアントだけのDOM生成ではできないのでしょうか? ただのDOM生成とajaxの違いは、サーバ側の変更が絡む要素の変更が必要かそうでないかという事ですね。 ただ画像をクリック時にへんこうするだけならサーバ側から何ももらう必要はないので この場合はただのDOM生成。 対戦ゲームなどサーバ側での変化を受け取って一部の要素をへんこうするなら、ajaxでないと不可能という事ですね。 >>> (2)の場合は 画面Aのままで、ボタン等の操作をJavaScriptが感知したうえで DOM というAPIを使って、画面AのHTMLを動的に変更します。 この場合、画面Aを表示中にサーバーとのやりとりはありませんので JavaScript内に表示の切り替えの判断に使う アルゴリズムやデータは あらかじめブラウザに送っておく必要があります。 これはサーバサイドに何も送らないので、クリック時にjsでDOM操作して、 要素をJSがフロント側で生成して一部要素を変更することですね。 これはローカル環境でも実行できますが、サーバとのやり取りが一切ないので、 チャットなどの自分の端末以外で何かへんこうがあっても当然何も対応ができないという事ですね。 対戦ゲームなどもこれでは対応できないですね。 シンプルなSPAならこれでも大丈夫そうですが。 >>> > もしかして、ページ遷移なしで一部の要素だけを変更する作業はフロントjsでしかで きず、 >サーバサイドではできないのでしょうか? その通りです。 AJAXでは更新部分のデータは、サーバーサイドで作っていますが それを表示画面に反映させるというダイナミックHTMLの処理は、 JavaScript等のクライアントサイドスクリプトの仕事です。 ajaxはサーバサイドで作った要素をサーバから受け取り、 ページ遷移をせずに一部分だけ変更するjsの技術という事ですね。 PHPだけでの場合はページ遷移をしないと絶対にいけないというのが、 ajaxとの決定的な違いですね。 index.phpなどサーバサイドでページすべてを作成してページ遷移するタイプ、 ページ遷移するがajaxとただのDOM生成はページ遷移しないと分けて考えます。
- superside0
- ベストアンサー率64% (461/711)
> サーバサイドのプログラミングならDOM操作や生成などすべて行えるのかと思ったの ですが、 > DOM操作、生成はやはりJSしかできないのですね。 サーバーサイドで、HTMLを直接作ることはもちろん可能です。 (一般的なCGIはそうですので) しかし、今回のAJAXでの話でいえば、既に生成が終わっているHTMLに対して 変更を行うことになるのでDOMを使うことになります。 (DOMとは、JavaScriptでHTML(やXML)を加工するためのAPIのことですので) つまり、ボタン操作などを受けてサーバーサイドで再度HTMLを作り直すのではなく、 サーバーサイドで生成するのは、 変更部の値のみ(数値や文字列の生データまたはJSONまたはXML)で それをJavaScriptが受けとってDOMを操作して表示に反映させることになります。 >XMLHttpRequest.send()のsendメソッドのことですね。 >恐らくこれはサーバサイドに情報を送るメソッドでしょうね。 > これが実行されたタイミングと正常に終わったタイミングと実行されるタイミングが 違うのですね。 そういうことです。 ブラウザからサーバーへリクエストを送信(send) ↓ サーバーがリクエストを受信 サーバーがそのリクエストを処理 サーバーから結果を送信 ↓ ブラウザが処理結果を受信 というフローですので、ボタン等の操作をしてすぐに応答がある訳ではありません。 このサーバーからの応答を受信完了するまで、JavaScriptでの処理待たせてしまっていると、 その間、ブラウザが”固まったまま”で、別の操作ができないということになってしまいます。 そこで、AJAXでは、サーバーへのリクエスト送信(send)と その応答の受信完了を 別々の処理として”非同期に”行うように工夫します。 > DOM操作はあくまでフロントのJSの役目なので、サーバの処理か終わって送られた情 報を受け取ってから初めて、 行なわれるのですね。 その通りです。
お礼
>>> なお、DOMの操作をするのは、あくまでもJavaScriptの仕事なので、 正確には「サーバー側でDOMを作っている」のではなく、 サーバー側でDOMに入れる値を作って、それを受け取ったJavaScriptがDOM要素を 生成していることになりますが。 ajaxの場合は必ず値だけサーバサイドで作って、 その値をサーバからもらったJSがDOM生成するのでしょうか? もしかして、ページ遷移なしで一部の要素だけを変更する作業はフロントjsでしかできず、 サーバサイドではできないのでしょうか? それとも、実はajaxを使わずにphpで動的に要素を作った場合は、htmlタグをphpが作って、 ブラウザに渡すので、要素自体を作成しているのですね。
- superside0
- ベストアンサー率64% (461/711)
> つまりサーバ側でDOMを作ったらajax、ブラウザ上で作ったらただのDOM生成という事ですか? AJAXとは、JavaScriptで XML通信を非同期に行うことですから そういうことになりますね。 たったそれだけの違いではありますが、GoogleMapのように、 ボタンやマウスの操作で、画面の推移なしに表示を書き換えたいときでも、 サーバーからブウウザには必要最小限のマップデータを送るだけで済むようになります。 なお、DOMの操作をするのは、あくまでもJavaScriptの仕事なので、 正確には「サーバー側でDOMを作っている」のではなく、 サーバー側でDOMに入れる値を作って、それを受け取ったJavaScriptがDOM要素を 生成していることになりますが。 1 > result.textContent = xhr.responseText; > 自分で作った変数resultの中に通信に両方成功した場合サーバ側のPHPが生成したDOM要素を代入するという事をやっているのでしょうか? そういうことです。 正確にいうと「サーバー側のPHPが生成した値を、 DOM要素の1つを示しているresultというオブジェクトのtextContentプロパティーに代入している」 ことになります。 > その結果、処理結果を表記するhtml<div id="result"></div>の中に、代入された中身が表記されるという事ですか? 事前に、resultというオブジェクトが id="result"というDOM要素を示す ものとして宣言されているなら、その通りです。 ソース中に、var result = document.getElementById('result'); とあるので、これのことですが。 こういったDOMの操作部分は、AJAXだからといってなんら変わらないです。 2. >下記のloadstartとloadなどう違うのでしょうか? loadstartというイベントはsendが始まったタイミングで発行されるイベントで、 loadはそれが正常終わったときに発行されるイベントです。 ただし、このソース中の loadstartやloadを使っている部分は /* */ で囲んであって、コメント扱いなので、JavaScrpitとしては動作していません。 なお、AJAXの'A"は、非同期のことなので、 JavaScriptでは、サーバーからの応答が終了したというイベントを待って そのタイミングでDOMの操作などの処理する必要があります。 このソースでいうと、これを行っているのが readyStateの値が更新されるたびに呼び出される xhr.onreadystatechange の function定義部で この中で readyStateやstatusを使って、通信開始/エラー終了/正常終了 のどの状態かを判断して、 <div id="result"></div>内の文字を切り替えていますね。
お礼
ありがとうございます。 >>> なお、DOMの操作をするのは、あくまでもJavaScriptの仕事なので、 正確には「サーバー側でDOMを作っている」のではなく、 サーバー側でDOMに入れる値を作って、それを受け取ったJavaScriptがDOM要素を 生成していることになりますが。 サーバサイドのプログラミングならDOM操作や生成などすべて行えるのかと思ったのですが、 DOM操作、生成はやはりJSしかできないのですね。 XMLHttpRequest.send()のsendメソッドのことですね。 恐らくこれはサーバサイドに情報を送るメソッドでしょうね。 これが実行されたタイミングと正常に終わったタイミングと実行されるタイミングが違うのですね。 よって こちらがサーバに情報を送ったタイミングという事でしょうか? つまり、通信を開始したタイミングでもある。 xhr.addEventListener('loadstart', function() { // 画面に通信中と表記 result.textContent = '通信中...'; }, false); 受け取った情報でDOM操作まで問題なく終了したタイミングではなく、そこまで行っていない、少し手前の、 こちらがサーバから情報を問題なく受け取ったタイミングという事でしょうか? つまり、通信を無事終了したタイミングでもある。 // 画面に通信中と表記 xhr.addEventListener('load', function() { result.textContent = xhr.responseText; }, false); >> なお、AJAXの'A"は、非同期のことなので、 JavaScriptでは、サーバーからの応答が終了したというイベントを待って そのタイミングでDOMの操作などの処理する必要があります。 このソースでいうと、これを行っているのが readyStateの値が更新されるたびに呼び出される xhr.onreadystatechange の function定義部で この中で readyStateやstatusを使って、通信開始/エラー終了/正常終了 のどの状態かを判断して、 <div id="result"></div>内の文字を切り替えていますね。 DOM操作はあくまでフロントのJSの役目なので、サーバの処理か終わって送られた情報を受け取ってから初めて、 行なわれるのですね。 下記の認識でよいでしょうか? xhr.onreadystatechange = function() { // readyStateやstatusを使って、通信開始/エラー終了/正常終了 のどの状態かを判断 if (xhr.readyState === 4) { if (xhr.status === 200) { result.textContent = xhr.responseText; } else { // 通信の状態によって<div id="result"></div>内の文字を切り替えて、通信がうまくいったかどうかを示している result.textContent = 'サーバーエラーが発生しました。'; } } else { // 通信の状態によって<div id="result"></div>内の文字を切り替えて、通信がうまくいったかどうかを示している result.textContent = '通信中...'; } }; /* xhr.addEventListener('loadstart', function() { // 通信の状態によって<div id="result"></div>内の文字を切り替えて、通信がうまくいったかどうかを示している result.textContent = '通信中...'; }, false);
お礼
ありがとうございます。 >>> ちょっと勘違いがあるようです。 サーバー側でHTMLを作る手法は、様々あります。 ・HTML文書内に可変部だけPHPプログラムでコーディングするという方法は一般的ですし、 ・静的HTMLから別のPHPをSSIで読み込む(exec やinclude)という方法もありますし、 ・PHPから静的HTMLを雛形として読み込んで一部を書き換えてからブラウザに出力するという方法も可能で、 いろいろです。 ですが、 いまは、サーバーサイドでどんな仕組みでHTMLを生成するのかは、 本題ではありません。 php単体でajaxを使わない場合は jsのように一部の要素だけサーバサイドで作成することは可能なのですね。 ただそれでもajaxと違い変更したphpファイルをサーバから再度受け取らないといけないので、 ページ遷移しないといけない事が唯一の違いなのですね。 また、htmlファイルにインクルードすることで、外部のPHPを取り込むことが出来るので、 大元のhtmlファイルは拡張子をphpにしなくてもインクルードするファイルがphpになっていれば問題ないのですね。 しかし、phpとajaxの合わせ技を使えば、phpを使ってサーバサイドで作った、要素を非同期に取り込むことが出来るので、 ページ遷移しなくても良くなるのですね。
補足
>>> 前にも説明しましたが、世界中の詳細な地図データというのは、データが大きするからです。 もし、クライアントだけで画面遷移なしに世界のどこにでも移動できる地図アプリを作ろうとすれば 世界中の詳細な地図データを あらかじめクライアントがもっておかねばなりません。 (カーナビでのDVDやHDDに入っている地図データがこの方式ですね)(日本だけのデータですが) dom生成だけで行うとサーバとの通信ができないので、 地図のデータを事前にすべてクライアントPCが持っていないといけない問題が起こるので、必要になった場合のみその部分をサーバから持ってくるためにajaxが必要という事ですね。