衚珟力豊かなJavaScriptHTTP

内容







ネットワヌクが䜜成された倢は、私たちが情報を共有し、通信する共通の情報空間です。 その普遍性は䞍可欠な郚分です。ハむパヌテキストリンクは、個人情報、ロヌカル情報、グロヌバル情報、䞋曞き、怜蚌枈みテキストなど、どこにでも導くこずができたす。



Tim Bernes-Lee、World Wide Web非垞に短い個人史



プロトコル



ブラりザヌのアドレスバヌにeloquentjavascript.net/17_http.htmlず入力するず、ブラりザヌは最初にeloquentjavascript.netずいう名前に関連付けられおいるサヌバヌアドレスを認識し、HTTPのデフォルトポヌトであるポヌト80でTCP接続を開こうずしたす。 サヌバヌが存圚し、接続を受け入れる堎合、ブラりザは次のようなものを送信したす。



GET /17_http.html HTTP / 1.1

ホストeloquentjavascript.net

ナヌザヌ゚ヌゞェントブラりザヌ名



サヌバヌは同じ接続を介しお応答したす。



HTTP / 1.1 200 OK

コンテンツの長さ65585

コンテンツタむプテキスト/ html

最終倉曎日2014幎4月9日氎曜日10:48:09 GMT



<doctype html>

...ドキュメントの残りの郚分



ブラりザは、空の行の埌の回答の埌に来る郚分を取埗し、HTMLドキュメントずしお衚瀺したす。



クラむアントから送信された情報はリク゚ストず呌ばれたす。 次の行で始たりたす。



GET /17_http.html HTTP / 1.1



最初の蚀葉はリク゚ストメ゜ッドです。 GETは、特定のリ゜ヌスを取埗する必芁があるこずを意味したす。 他の䞀般的な方法は、削陀のDELETE、眮換のPUT、および情報の送信のPOSTです。 サヌバヌは、受信した各芁求を実行する必芁がないこずに泚意しおください。 ランダムなサむトを遞択し、メむンペヌゞを削陀するように指瀺するず、圌はおそらく拒吊したす。



メ゜ッド名の埌の郚分は、リク゚ストが送信されたリ゜ヌスぞのパスです。 最も単玔な堎合、リ゜ヌスはサヌバヌ䞊の単なるファむルですが、プロトコルはこの機胜に限定されたせん。 リ゜ヌスは、ファむルずしお転送できるものであれば䜕でもかたいたせん。 倚くのサヌバヌがその堎で応答を䜜成したす。 たずえば、twitter.com / marijnjhを開くず、サヌバヌはmarijnjhナヌザヌデヌタベヌスを調べ、開く堎合は、そのナヌザヌのプロファむルペヌゞを䜜成したす。



リ゜ヌスぞのパスの埌、ク゚リの最初の行にはHTTP / 1.1が蚘茉されおおり、䜿甚するHTTPプロトコルのバヌゞョンが報告されたす。



サヌバヌの応答もプロトコルバヌゞョンで始たり、応答ステヌタスが続きたす-最初に3桁のコヌド、次に行。



HTTP / 1.1 200 OK



2で始たるステヌタスコヌドは、リク゚ストが成功したこずを瀺したす。 4で始たるコヌドは、䜕かがおかしいこずを意味したす。 404は最も有名なHTTPステヌタスであり、芁求されたリ゜ヌスが芋぀からなかったこずを瀺したす。 5で始たるコヌドは、サヌバヌで゚ラヌが発生したこずを瀺しおいたすが、リク゚ストの障害によるものではありたせん。



芁求たたは応答の最初の行の埌には、任意の数のヘッダヌ行を続けるこずができたす。 これらは、芁求たたは応答に関する远加情報を瀺す「名前倀」の圢匏の文字列です。 これらのヘッダヌは䟋に含たれおいたす。



コンテンツの長さ65585

コンテンツタむプテキスト/ html

最終倉曎日2014幎4月9日氎曜日10:48:09 GMT



これにより、応答で受信したドキュメントのサむズずタむプが決たりたす。 この堎合、これはサむズが65,585バむトのHTMLドキュメントです。 たた、ドキュメントが最埌に倉曎された日時も瀺したす。



ほずんどの堎合、芁求たたは応答に含めるヘッダヌをクラむアントたたはサヌバヌが決定したすが、䞀郚のヘッダヌは必須です。 たずえば、1぀のサヌバヌが同じIPアドレスで倚くのホスト名を提䟛できるため、ホスト名を瀺すホストをリク゚ストに含める必芁がありたす。このヘッダヌがないず、サヌバヌはクラむアントが通信しようずしおいるホストを認識したせん。



ヘッダヌの埌に、芁求ず応答の䞡方が空の行を瀺し、その埌に送信デヌタを含む本文が続く堎合がありたす。 GETおよびDELETE芁求は远加デヌタを転送したせんが、PUTおよびPOSTは送信したす。 ゚ラヌメッセヌゞなどの䞀郚の応答には、本文は必芁ありたせん。



ブラりザヌずHTTP



䟋で芋たように、アドレスバヌにURLを入力するず、ブラりザヌはリク゚ストを送信したす。 受信したHTMLドキュメントに画像やJavaScriptファむルなどの他のファむルぞの参照が含たれおいる堎合、それらもサヌバヌから芁求されたす。



平均的な手のWebサむトには、10〜200個のリ゜ヌスを簡単に含めるこずができたす。 より速くリク゚ストできるようにするために、ブラりザは同時に耇数のリク゚ストを行い、リク゚ストが次々に終了するのを埅ちたせん。 このようなドキュメントは、垞にGETリク゚ストを通じおリク゚ストされたす。



HTMLペヌゞには、ナヌザヌが情報を入力しおサヌバヌに送信できるフォヌムがありたす。 フォヌムの䟋を次に瀺したす。



<form method="GET" action="example/message.html"> <p>: <input type="text" name="name"></p> <p>:<br><textarea name="message"></textarea></p> <p><button type="submit"> </button></p> </form>
      
      







このコヌドは、2぀のフィヌルドを持぀フォヌムを蚘述しおいたす。小さなフィヌルドは名前を芁求し、倧きなフィヌルドはメッセヌゞずしお入力したす。 [送信]ボタンをクリックするず、これらのフィヌルドの情報がク゚リ文字列に゚ンコヌドされたす。 芁玠のメ゜ッド属性がGETの堎合、たたはたったく指定されおいない堎合、ク゚リ文字列はアクションフィヌルドのURLに配眮され、ブラりザヌはこのURLを䜿甚しおGET芁求を行いたす。



GET /example/message.html?name=Jean&message=Yes%3F HTTP / 1.1



ク゚リ行の先頭は疑問笊で瀺されたす。 その埌、フォヌムフィヌルドの名前属性ずこれらのフィヌルドの内容に察応する名前ず倀のペアがありたす。 アンパサンドを䜿甚しおそれらを区切りたす。



この䟋で送信されるメッセヌゞには、文字列「Yes」が含たれおいたすが、疑問笊は奇劙なコヌドに眮き換えられおいたす。 ク゚リ文字列の䞀郚の文字ぱスケヌプする必芁がありたす。 疑問笊を含み、code3Fで衚されたす。 すべおの圢匏には文字を゚スケヌプする方法が必芁であるずいう、曞かれおいない芏則がありたす。 URL゚ンコヌドず呌ばれるこのルヌルは、パヌセントの埌に、文字コヌドを衚す2桁の16進数を䜿甚したす。 10進法の3Fは63であり、これは疑問笊コヌドです。 JavaScriptには、゚ンコヌドおよびデコヌド甚の関数encodeURIComponentおよびdecodeURIComponentがありたす。



 console.log(encodeURIComponent("Hello & goodbye")); // → Hello%20%26%20goodbye console.log(decodeURIComponent("Hello%20%26%20goodbye")); // → Hello & goodbye
      
      







前の䟋のフォヌムのmethod属性をPOSTに倉曎するず、フォヌムを含むHTTPリク゚ストはPOSTメ゜ッドを䜿甚しお送信され、URLに远加するのではなく、リク゚スト本文でリク゚スト文字列を送信したす。



POST /example/message.html HTTP / 1.1

コンテンツの長さ24

コンテンツタむプアプリケヌション/ x-www-form-urlencoded



名前=ゞャンメッセヌゞ=はい3F



慣䟋により、GETメ゜ッドは、怜玢などの副䜜甚のないク゚リに䜿甚されたす。 サヌバヌ䞊の䜕かを倉曎するリク゚スト-新しいアカりントの䜜成たたはメッセヌゞの投皿は、POSTメ゜ッドを䜿甚しお送信する必芁がありたす。 ブラりザなどのクラむアントプログラムは、POSTリク゚ストを行う必芁がないこずを認識しおおり、たずえば、ナヌザヌがすぐに必芁ずするコンテンツをダりンロヌドするなど、ナヌザヌに気付かれずにGETリク゚ストを行うこずもありたす。



次の章では、フォヌムに戻り、JavaScriptを䜿甚しおフォヌムを実行する方法に぀いお説明したす。



XMLHttpRequest



ブラりザのJavaScriptがHTTPリク゚ストを䜜成できるむンタヌフェむスは、XMLHttpRequestず呌ばれたす文字のサむズがどのようにゞャンプするかに泚意しおください。 1990幎代埌半にMicrosoftでInternet Explorer甚に開発されたした。 圓時、XML圢匏はビゞネス゜フトりェアの䞖界で非垞に人気がありたした。この䞖界では、Microsoftは垞に家庭にいるず感じおいたした。 非垞に人気があったため、XMLの省略圢はHTTPを操䜜するためのむンタヌフェヌスの名前に固定されおいたしたが、埌者はXMLにたったく関連付けられおいたせん。



それでも、名前は完党に無意味ではありたせん。 このむンタヌフェむスを䜿甚するず、回答をXMLドキュメントのように解析できたす。 2぀の異なるもの芁求ず回答の解析を1぀に混ぜるこずは、もちろん、嫌なデザむンですが、䜕ができるのでしょう。



XMLHttpRequestむンタヌフェむスがInternet Explorerに远加されたずき、以前は非垞に困難であったこずを行うこずが可胜になりたした。 たずえば、ナヌザヌがテキストボックスに䜕かを入力しおいる間に、サむトはプロンプトのリストを衚瀺し始めたした。 スクリプトは、ナヌザヌがテキストを入力するず同時に、HTTPを介しおサヌバヌにテキストを送信したす。 可胜な入力オプション甚のデヌタベヌスを備えたサヌバヌは、゚ントリの䞭から゚ントリを探し、衚瀺のためにそれらを返したす。 ずおもクヌルに芋えたした。サむトを操䜜するたびにペヌゞ党䜓がリロヌドされるのを埅぀こずに慣れおいたした。



圓時のもう1぀の重芁なブラりザであるMozilla埌のFirefoxは遅れを取りたくありたせんでした。 同様のこずができるようにするために、Mozillaはむンタヌフェヌスを名前ずずもにコピヌしたした。 次䞖代のブラりザヌがそれに続き、今日ではXMLHttpRequestが事実䞊の暙準ずなっおいたす。



提出䟝頌



単玔なリク゚ストを送信するには、XMLHttpRequestコンストラクタヌでリク゚ストオブゞェクトを䜜成し、openメ゜ッドずsendメ゜ッドを呌び出したす。



 var req = new XMLHttpRequest(); req.open("GET", "example/data.txt", false); req.send(null); console.log(req.responseText); // → This is the content of data.txt
      
      







openメ゜ッドはリク゚ストを蚭定したす。 この䟋では、サンプル/ data.txtファむルに察しおGETリク゚ストを行うこずにしたした。 プロトコル名で始たらないURLたずえば、http :)は盞察ず呌ばれたす。぀たり、珟圚のドキュメントに察しお盞察的に解釈されたす。 スラッシュ/で始たる堎合、珟圚のパスサヌバヌ名の埌の郚分を眮き換えたす。 それ以倖の堎合、珟圚のパスの最埌のスラッシュたでの郚分が盞察URLの前に配眮されたす。



リク゚ストを開いた埌、sendメ゜ッドを䜿甚しお送信できたす。 匕数はリク゚ストの本文です。 GETリク゚ストの堎合、nullが䜿甚されたす。 openの3番目の匕数がfalseの堎合、sendはリク゚ストぞの応答が受信された埌にのみ返されたす。 応答本文を取埗するには、芁求オブゞェクトのresponseTextプロパティを読み取りたす。



応答オブゞェクトから他の情報を取埗できたす。 ステヌタスコヌドはstatusプロパティで䜿甚でき、ステヌタステキストはstatusTextにありたす。 芋出しはgetResponseHeaderから読み取るこずができたす。



 var req = new XMLHttpRequest(); req.open("GET", "example/data.txt", false); req.send(null); console.log(req.status, req.statusText); // → 200 OK console.log(req.getResponseHeader("content-type")); // → text/plain
      
      







ヘッダヌ名は倧文字ず小文字が区別されたせん。 通垞、「Content-Type」など、各単語の先頭に倧文字が䜿甚されたすが、「content-type」たたは「cOnTeNt-TyPe」は同じタむトルを衚したす。



ブラりザ自䜓は、「ホスト」などのヘッダヌを远加したす。これらのヘッダヌは、サヌバヌがボディサむズを蚈算するために必芁です。 ただし、setRequestHeaderメ゜ッドを䜿甚しお独自のヘッダヌを远加できたす。 これは特別な堎合に必芁であり、アクセスしおいるサヌバヌの支揎が必芁です-凊理できないヘッダヌは無芖しおも構いたせん。



非同期リク゚スト



この䟋では、芁求は送信呌び出しが終了したずきに完了したした。 responseTextなどのプロパティがすぐに䜿甚可胜になるため、これは䟿利です。 しかし、これは、ブラりザヌずサヌバヌが互いに通信しおいる間、プログラムが埅機するこずを意味したす。 䞍十分な通信、匱いサヌバヌ、たたは倧きなファむルの堎合、これには長い時間がかかりたす。 たた、プログラムがスタンバむモヌドになっおいる間はむベントハンドラヌが機胜しないため、これは悪いこずです。ドキュメントはナヌザヌのアクションに応答しなくなりたす。



openの3番目の匕数ずしおtrueを枡すず、リク゚ストは非同期になりたす。 ぀たり、sendを呌び出すず、リク゚ストは送信のためにキュヌに入れられたす。 プログラムは匕き続き動䜜し、ブラりザはバックグラりンドでデヌタを送受信したす。



ただし、リク゚ストの凊理䞭は、応答を受け取りたせん。 デヌタが到着しお準備ができおいるずいう通知メカニズムが必芁です。 これを行うには、「load」むベントをリッスンする必芁がありたす。



 var req = new XMLHttpRequest(); req.open("GET", "example/data.txt", true); req.addEventListener("load", function() { console.log("Done:", req.status); }); req.send(null);
      
      







第15章のrequestAnimationFrameを呌び出すように、このコヌドは非同期プログラミングスタむルを䜿甚するように匷制し、リク゚スト埌にコヌドを実行するように関数をラップし、適切なタむミングでこの関数の呌び出しを配眮し​​たす。 これに぀いおは埌で説明したす。



XMLデヌタの取埗





XMLHttpRequestによっお返されるリ゜ヌスがXMLドキュメントの堎合、responseXMLプロパティにはドキュメントの解析されたビュヌが含たれたす。 スタむルプロパティのような固有のHTML機胜がないこずを陀いお、DOMず同様の方法で機胜したす。 responseXMLに含たれるオブゞェクトは、ドキュメントオブゞェクトに察応したす。 そのdocumentElementプロパティは、倖郚XMLドキュメントタグを参照したす。 次のドキュメント䟋/ fruit.xmlでは、このタグは次のようになりたす。



 <fruits> <fruit name="banana" color="yellow"/> <fruit name="lemon" color="yellow"/> <fruit name="cherry" color="red"/> </fruits>
      
      







次のようなファむルを取埗できたす。



 var req = new XMLHttpRequest(); req.open("GET", "example/fruit.xml", false); req.send(null); console.log(req.responseXML.querySelectorAll("fruit").length); // → 3
      
      







XMLドキュメントを䜿甚しお、構造化された情報をサヌバヌず亀換できたす。 それらの圢匏-ネストされたタグ-は、ほずんどのデヌタを保存するのに適しおいたす。少なくずもテキストファむルよりも優れおいたす。 DOMむンタヌフェヌスは、情報を抜出するずいう点では䞍栌奜であり、XML文曞はかなり冗長です。 通垞は、プログラムず人の䞡方の読み取りず曞き蟌みが簡単なJSON圢匏のデヌタを䜿甚しお通信するこずをお勧めしたす。



 var req = new XMLHttpRequest(); req.open("GET", "example/fruit.json", false); req.send(null); console.log(JSON.parse(req.responseText)); // → {banana: "yellow", lemon: "yellow", cherry: "red"}
      
      







HTTPのサンドボックス



WebペヌゞからのHTTP芁求は、セキュリティ䞊の問題を匕き起こしたす。 スクリプトを制埡しおいる人は、実行䞭のコンピュヌタヌを所有しおいるナヌザヌの興味ずは異なる興味を持぀堎合がありたす。 具䜓的には、themafia.orgにアクセスした堎合、ブラりザの情報を識別子ずしお䜿甚し、すべおのお金をマフィアアカりントに送信するコマンドを䞎えお、スクリプトがmybank.comにリク゚ストできるようにしたくありたせん。



Webサむトはこのような攻撃から身を守るこずができたすが、これにはある皋床の努力が必芁であり、倚くのサむトはこれに察凊しおいたせん。 このため、ブラりザは、スクリプトが他のドメむンthemafia.orgやmybank.comなどの名前にリク゚ストを送信するこずを防ぐこずで、それらを保護したす。



これは、正圓な理由で異なるドメむンにアクセスする必芁があるシステムの開発を劚げる可胜性がありたす。 幞いなこずに、サヌバヌは応答に次のヘッダヌを含めるこずができ、リク゚ストが他のドメむンから送信される可胜性があるこずをブラりザヌに説明したす。



Access-Control-Allow-Origin*



抜象リク゚スト



第10章では、AMDモゞュラヌシステムの実装で、仮想関数backgroundReadFileを䜿甚したした。 圌女はファむル名ず関数を受け入れ、ファむルの内容を読み取った埌にこの関数を呌び出したした。 この関数の簡単な実装は次のずおりです。



 function backgroundReadFile(url, callback) { var req = new XMLHttpRequest(); req.open("GET", url, true); req.addEventListener("load", function() { if (req.status < 400) callback(req.responseText); }); req.send(null); }
      
      







単玔な抜象化により、単玔なGET芁求に察するXMLHttpRequestの䜿甚が簡玠化されたす。 HTTPリク゚ストを行うプログラムを䜜成しおいる堎合、ヘルパヌ関数を䜿甚するず、niceいXMLHttpRequestテンプレヌトを垞に繰り返す必芁がなくなりたす。



コヌルバック匕数は、このような関数を説明するためによく䜿甚される甚語です。 埌でコヌルバックできるように、コヌルバック関数は別のコヌドに枡されたす。



プログラム専甚に調敎された補助HTTP関数を簡単に䜜成できたす。 前のものはGETリク゚ストのみを行い、リク゚ストのヘッダヌたたは本文を制埡するこずはできたせん。 POSTリク゚スト甚に別のオプション、たたは異なるリク゚ストをサポヌトするより䞀般的なオプションを䜜成できたす。 倚くのJavaScriptラむブラリは、XMLHttpRequestのラッパヌを提䟛したす。



このラッパヌの䞻な問題ぱラヌ凊理です。 芁求が゚ラヌを瀺すステヌタスコヌド400以䞊を返す堎合、䜕もしたせん。 これは正垞な堎合もありたすが、情報を受信しお​​いるこずを瀺すダりンロヌドむンゞケヌタヌをペヌゞに配眮したずしたす。 サヌバヌがクラッシュしたか接続が䞭断されたためにリク゚ストが倱敗した堎合、ペヌゞは䜕かでビゞヌであるように芋せたす。 ナヌザヌは少し埅っおから退屈し、サむトがなんらかの愚かだず刀断したす。



アクションを実行できるように、倱敗したリク゚ストに関する譊告を受け取るオプションが必芁です。 たずえば、ダりンロヌドメッセヌゞを削陀しお、ナヌザヌに䜕か問題があったこずを䌝えるこずができたす。



非同期コヌドの゚ラヌ凊理は、同期コヌドよりもさらに耇雑です。 倚くの堎合、䜜業の䞀郚を分離しおコヌルバック関数に配眮する必芁があるため、tryブロックのスコヌプは無意味になりたす。 次のコヌドでは、backgroundReadFileの呌び出しがすぐに返されるため、䟋倖はキャッチされたせん。 その埌、コントロヌルはtryブロックを離れ、そこからの関数は呌び出されたせん。



 try { backgroundReadFile("example/data.txt", function(text) { if (text != "expected") throw new Error("That was unexpected"); }); } catch (e) { console.log("Hello from the catch block"); }
      
      







倱敗したリク゚ストを凊理するには、远加の関数をラッパヌに枡し、問題が発生した堎合にそれを呌び出す必芁がありたす。 別のオプションは、芁求が倱敗した堎合、問題の説明を含む远加の匕数がコヌルバック関数に枡されるずいう芏則を䜿甚するこずです。 䟋



 function getURL(url, callback) { var req = new XMLHttpRequest(); req.open("GET", url, true); req.addEventListener("load", function() { if (req.status < 400) callback(req.responseText); else callback(null, new Error("Request failed: " + req.statusText)); }); req.addEventListener("error", function() { callback(null, new Error("Network error")); }); req.send(null); }
      
      







呌び出しに問題がある堎合に起動する゚ラヌむベントハンドラヌを远加したした。 たた、リク゚ストが゚ラヌを瀺すステヌタスで完了するず、゚ラヌ匕数を䜿甚しおコヌルバック関数を呌び出したす。



getURLを䜿甚するコヌドは、゚ラヌが返されたかどうかを確認し、゚ラヌがある堎合は凊理する必芁がありたす。



 getURL("data/nonsense.txt", function(content, error) { if (error != null) console.log("Failed to fetch nonsense.txt: " + error); else console.log("nonsense.txt: " + content); });
      
      







䟋倖を陀き、これは圹に立ちたせん。 耇数の非同期アクションを連続しお実行するず、try / catchブロックで各ハンドラヌをラップしおいない限りチェヌン内の任意の時点で䟋倖がトップレベルで発生し、チェヌン党䜓に割り蟌みたす。



玄束



単玔なコヌルバックの圢匏で耇雑なプロゞェクトの非同期コヌドを蚘述するこずは困難です。 ゚ラヌチェックを忘れたり、予期しない䟋倖がプログラムを突然䞭断したりするこずは非垞に簡単です。 さらに、正しい゚ラヌ凊理を敎理し、いく぀かの連続したコヌルバックを通じお゚ラヌを枡すこずは非垞に面倒です。



远加の抜象化を䜿甚しお、この問題を解決するために倚くの詊みが行われたした。 最も成功した詊みの1぀はプロミスず呌ばれたす。 Promiseは、枡すこずができるオブゞェクトで非同期アクションをラップし、アクションが完了たたは倱敗したずきに特定のこずを行う必芁がありたす。 このようなむンタヌフェヌスはすでにJavaScriptの珟圚のバヌゞョンの䞀郚になっおおり、叀いバヌゞョンではラむブラリずしお䜿甚できたす。



promiseむンタヌフェヌスは特に盎感的ではありたせんが、匷力です。 この章では、郚分的にのみ説明したす。 詳现に぀いおは、 www.promisejs.orgをご芧ください。



promisesオブゞェクトを䜜成するには、Promiseコンストラクタヌを呌び出しお、非同期アクションを初期化する機胜を䞎えたす。 コンストラクタヌはこの関数を呌び出し、2぀の匕数を枡したす。これらの匕数自䜓も関数です。 最初は成功した堎合に呌び出され、もう䞀方は倱敗した堎合に呌び出されたす。



たた、GETリク゚ストのラッパヌもありたすが、今回はこれが玄束を返したす。 今ではgetず呌ぶだけです。



 function get(url) { return new Promise(function(succeed, fail) { var req = new XMLHttpRequest(); req.open("GET", url, true); req.addEventListener("load", function() { if (req.status < 400) succeed(req.responseText); else fail(new Error("Request failed: " + req.statusText)); }); req.addEventListener("error", function() { fail(new Error("Network error")); }); req.send(null); }); }
      
      







関数自䜓ぞのむンタヌフェヌスが簡玠化されおいるこずに泚意しおください。 圌女にURLを枡すず、圌女は玄束を返したす。 芁求の出力のハンドラヌずしお機胜したす。 thenメ゜ッドがあり、2぀の関数で呌び出されたす。1぀は凊理の成功、もう1぀は倱敗です。



 get("example/data.txt").then(function(text) { console.log("data.txt: " + text); }, function(error) { console.log("Failed to fetch data.txt: " + error); });
      
      







これたでのずころ、これはただ私たちがすでにやったこずを衚珟する1぀の方法です。 䞀連のむベントがある堎合にのみ、顕著な違いが芋えるようになりたす。



呌び出しは新しいプロミスを生成し、その結果成功ハンドラヌに枡される倀は、次に枡した最初の関数によっお返される倀に䟝存したす。 この関数は、远加の非同期䜜業が行われおいるこずを瀺す別のプロミスを返すこずができたす。 この堎合、そのずきに返されるpromiseは、ハンドラヌ関数によっお返されるpromiseを埅機し、同じ倀で成功たたは倱敗が発生したす。 ハンドラヌ関数がプロミスではない倀を返すず、thenが返すプロミスは成功し、その倀を結果ずしお䜿甚したす。



そのため、promiseの結果を倉曎するために䜿甚できたす。 たずえば、次の関数は、結果がJSONずしお解析された特定のURLのコンテンツであるプロミスを返したす。



 function getJSON(url) { return get(url).then(JSON.parse); }
      
      







thenぞの最埌の呌び出しは、倱敗ハンドラヌを瀺しおいたせんでした。 これは蚱容されたす。 ゚ラヌはそれたでに返されたプロミスに転送され、それが必芁になりたす。getJSONは䜕かがうたくいかなかったずきに䜕をすべきかを知りたせんが、それを呌び出すコヌドはそれを知っおいるこずが望たれたす。



promiseの䜿甚を瀺す䟋ずしお、サヌバヌからJSONファむルの数を受け取り、リク゚ストの実行䞭に「ダりンロヌド」ずいう単語を衚瀺するプログラムを䜜成したす。 ファむルには、人に関する情報ず、父芪、母芪、配偶者などの他の人に関する情報を含む他のファむルぞのリンクが含たれおいたす。



example / bert.jsonから配偶者の母芪の名前を取埗する必芁がありたす。 問題が発生した堎合は、「ダりンロヌド」ずいうテキストを削陀しお゚ラヌメッセヌゞを衚瀺する必芁がありたす。 玄束でそれを行う方法は次のずおりです。



 <script> function showMessage(msg) { var elt = document.createElement("div"); elt.textContent = msg; return document.body.appendChild(elt); } var loading = showMessage("..."); getJSON("example/bert.json").then(function(bert) { return getJSON(bert.spouse); }).then(function(spouse) { return getJSON(spouse.mother); }).then(function(mother) { showMessage(" - " + mother.name); }).catch(function(error) { showMessage(String(error)); }).then(function() { document.body.removeChild(loading); }); </script>
      
      







結果のプログラムは比范的コンパクトで読みやすいです。 catchメ゜ッドはthenに䌌おいたすが、倱敗した結果のハンドラヌのみを想定し、成功した堎合は倉曎されおいない結果をさらに枡したす。 プログラムの実行は、䟋倖をキャッチした埌、通垞の方法で続行されたす-try / catchの堎合ず同じです。 したがっお、ブヌトメッセヌゞを削陀する最埌の凊理は、障害が発生した堎合でも実行されたす。



promiseむンタヌフェヌスは、プログラムの実行を非同期に凊理するための別個の蚀語であるず想像できたす。 操䜜に必芁なメ゜ッドず関数ぞの远加の呌び出しは、コヌドに倚少奇劙な倖芳を䞎えたすが、すべおの゚ラヌを手動で凊理するほど䞍䟿ではありたせん。



HTTPを評䟡する



ブラりザクラむアントのJavaScriptプログラムがサヌバヌプログラムず通信するシステムを䜜成する堎合、そのような通信のいく぀かのモデリングオプションを䜿甚できたす。



䞀般的な方法は、リモヌトプロシヌゞャコヌルです。 このモデルでは、通信は通垞の関数呌び出しのパタヌンに埓っお進行し、これらの関数のみが別のコンピュヌタヌで実行されたす。呌び出しは、関数名ず匕数を含むサヌバヌぞの芁求を䜜成するこずです。芁求ぞの応答には戻り倀が含たれたす。



リモヌトプロシヌゞャコヌルを䜿甚する堎合、HTTPは通信の手段ずしおのみ機胜し、ほずんどの堎合、完党に非衚瀺にする抜象化レむダヌを蚘述したす。



別のアプロヌチは、HTTPリ゜ヌスずメ゜ッドの抂念に基づいお通信システムを構築するこずです。 addUserずいうリモヌトプロシヌゞャを呌び出す代わりに、/ users / larryに察しおPUT芁求を行いたす。関数の匕数でナヌザヌプロパティを゚ンコヌドする代わりに、ドキュメント圢匏を定矩するか、ナヌザヌを衚す既存の圢匏を䜿甚したす。新しいリ゜ヌスを䜜成するPUT芁求の本文は、単にこの圢匏のドキュメントになりたす。リ゜ヌスは、URL/ user / larryぞのGETリク゚ストを通じお取埗され、このリ゜ヌスを衚すドキュメントが返されたす。



2番目のアプロヌチは、リ゜ヌスキャッシングのサポヌトなど、いく぀かのHTTP機胜の䜿甚を簡玠化したすリ゜ヌスのコピヌはクラむアント偎に保存されたす。たた、リ゜ヌスの芳点から考えるこずは、機胜の芳点から考えるよりも簡単なので、䞀貫性のあるむンタヌフェヌスを䜜成するのにも圹立ちたす。



セキュリティずHTTPS



デヌタは、長く危険な経路に沿っおむンタヌネットを移動したす。目的地に着くには、コヌヒヌショップのWi-Fiネットワヌクからさたざたな組織や州が管理するネットワヌクに至るたで、あらゆる堎所をゞャンプする必芁がありたす。途䞭のどの時点でも、それらを読み取ったり、倉曎するこずさえできたす。



メヌルパスワヌドなどの秘密を保持する必芁がある堎合、たたは送金先の銀行口座番号など、目的地に倉曎する必芁がない堎合、単玔なHTTPでは䞍十分です。



URLがhttps//で始たるセキュアHTTPプロトコルは、HTTPトラフィックをラップするため、読み取りや倉曎が困難になりたす。最初に、クラむアントはサヌバヌが䞻匵するずおりであるこずを確認し、ブラりザヌが認識した暩限のある圓事者が発行した暗号蚌明曞を提瀺するこずをサヌバヌに芁求したす。次に、接続を通過するすべおのデヌタが暗号化され、盗聎や改ざんが防止されたす。



したがっお、すべおが正垞に機胜する堎合、HTTPSは、誰かが通信しおいる別のWebサむトのふりをする堎合ず、通信の傍受の堎合の䞡方を防ぎたす。それは完党ではなく、停の蚌明曞や盗たれた蚌明曞、たたは壊れたプログラムが原因でHTTPSが䜜業に察応できなかったケヌスがすでにありたす。それでも、HTTPを䜿甚するず、䜕か悪いこずが非垞に簡単に行われたす。たた、HTTPSをハッキングするには、政府機関たたは非垞に深刻な犯眪組織のみが適甚できる努力が必芁ですこれらの組織にたったく違いがない堎合もありたす。



たずめ



この章では、HTTPがむンタヌネット䞊のリ゜ヌスにアクセスするためのプロトコルであるこずを確認したした。クラむアントは、メ゜ッド通垞はGETずリ゜ヌスを定矩するパスを含む芁求を送信したす。サヌバヌは芁求の凊理方法を決定し、ステヌタスコヌドず応答本文で応答したす。芁求ず応答には、远加情報を䌝えるヘッダヌが含たれる堎合がありたす。



ブラりザは、ペヌゞをレンダリングするために必芁なリ゜ヌスを取埗するためにGET芁求を行いたす。このペヌゞには、ナヌザヌが入力した情報を、フォヌムの送信埌に䜜成されるリク゚ストで送信できるフォヌムが含たれおいる堎合がありたす。これに぀いおは、次の章で詳しく説明したす。



JavaScriptがブラりザからHTTP芁求を䜜成するためのむンタヌフェむスは、XMLHttpRequestず呌ばれたす。XMLプレフィックスは無芖できたすただし、それを蚘述する必芁がありたす。これは、芁求が完了するたですべおの䜜業をブロックする同期ず、芁求の終了を監芖するむベントハンドラヌのむンストヌルを必芁ずする非同期の2぀の方法で䜿甚できたす。ほずんどすべおの堎合、非同期方匏が優先されたす。ク゚リの䜜成は次のようになりたす。



 var req = new XMLHttpRequest(); req.open("GET", "example/data.txt", true); req.addEventListener("load", function() { console.log(req.statusCode); }); req.send(null);
      
      







非同期プログラミングは簡単なこずではありたせん。Promisesは、゚ラヌメッセヌゞず䟋倖を適切なハンドラヌにルヌティングし、重耇する゚ラヌを起こしやすい芁玠を抜象化するのを支揎する、よりシンプルなむンタヌフェむスです。



挔習



コンテンツ亀枉


HTTPでできるこずの1぀ですが、ただ説明しおいたせんが、コンテンツネゎシ゚ヌションです。芁求のAcceptヘッダヌを䜿甚しお、クラむアントが受信したいドキュメントの皮類をサヌバヌに䌝えるこずができたす。倚くのサヌバヌはそれを無芖したすが、サヌバヌがリ゜ヌスを゚ンコヌドするさたざたな方法を知っおいるずき、サヌバヌはヘッダヌを芋お、クラむアントが奜むヘッダヌを送信できたす。



eloquentjavascript.net/author URLは、クラむアントの芁求に応じお、プレヌンテキストずHTMLたたはJSONで応答するように構成されたす。これらの圢匏は、暙準化されたコンテンツタむプtext / plain、text / html、およびapplication / jsonによっお定矩されたす。



このリ゜ヌスの3぀の圢匏すべおを受信する芁求を送信したす。XMLHttpRequestオブゞェクトのsetRequestHeaderメ゜ッドを䜿甚しお、Acceptヘッダヌを目的のコンテンツタむプのいずれかに蚭定したす。開いた埌、送信する前にヘッダヌを蚭定しおください。



最埌に、アプリケヌション/虹+ナニコヌンなどのコンテンツを芁求しお、䜕が起こるかを確認しおください。



いく぀かの玄束を埅っおいたす


Promiseコンストラクタヌにはallメ゜ッドがあり、promiseの配列を受け取るず、配列に指定されたすべおのpromiseの完了を埅぀promiseを返したす。次に、成功した結果を返し、結果を含む配列を返したす。配列内のプロミスのいずれかが倱敗した堎合、䞀般的なプロミスも倱敗を返したす倱敗したプロミスの倀が配列から返されたす。



all関数を蚘述しお、このようなこずを詊しおください。



Promiseが完了した埌正垞に完了した堎合たたぱラヌが発生した堎合、゚ラヌたたは成功を再び返すこずはできず、それ以降の関数呌び出しは無芖されたす。これにより、玄束の゚ラヌ凊理を簡玠化できたす。



 function all(promises) { return new Promise(function(success, fail) { //  . }); } //  . all([]).then(function(array) { console.log("   []:", array); }); function soon(val) { return new Promise(function(success) { setTimeout(function() { success(val); }, Math.random() * 500); }); } all([soon(1), soon(2), soon(3)]).then(function(array) { console.log("   [1, 2, 3]:", array); }); function fail() { return new Promise(function(success, fail) { fail(new Error("")); }); } all([soon(1), fail(), soon(3)]).then(function(array) { console.log("     "); }, function(error) { if (error.message != "") console.log(" :", error); });
      
      






All Articles