できる気になっているJSを改めてチュートリアルからやってみる 23日目

~~ Fetch, Aside on promises ~~

最近ちょっとずつまた学びなおす必要が出てきたなぁと思い、いろいろプログラムを勉強しなおしているところなんですが、実はもう今使っている知識は古いのかもと思って、アップデートしようとおもいやってみる会。

実施するのは、この記事

MDN - Javascript

完全な初心者向けと書かれたチュートリアルは全然初心者向けではないって話。アップデートしていきましょう。

クライアントサイドWebAPI をやっています。

今日はFetchです

Fetch

Fetch APIは、基本的にはXHRの今風の代替品。最近になってブラウザに組み込まれたもので、非同期HTTPリクエストをJavaScriptで、開発者やほかのFetchの上に組まれたAPIから簡単に行えるようにするためのものです。

let request = new XMLHttpRequest();

// どのHTTPリクエストメソッドを使って取得するか
request.open('GET',url);

// レスポンスをどのような形式にしたいかを指定
request.responseType = 'text';

// リソースが返ってきたときの処理。 load イベントはレスポンスが返ってきたタイミングでやること
request.onload = function(){
   poemDisplay.textContent = request.response;
}

request.send();

の部分をfetchで書き換えます。

fetch(url).then(function(response){
   response.text().then(function(text){
       poemDisplay.textContent = text;
   })
});

んで、これでローカルサーバーからアクセスすればOK。

Fetchは何が起きているのか

fetch() メソッドが呼ばれ、取得したいリソースのURLが渡されています。これはXHRの request.open() の今どきな同等品で、さらにいうと .send() も不要。

そのあと、 .then() メソッドが fetch() の後に連鎖されています。このメソッドは Promises の一部で、非同期処理を行うための今風な JavaScriptに備わる機能です。fetch() はプロミスを返し、これはサーバから送られたレスポンスによって解決されます。

.then() を使ってプロミスが解決された後にコードを走らせることができ、コードとは内側で定義した関数にあたります。これは XHR版の onload イベントハンドラに相当します。

この関数には、fetch()のプロミスが解決された際に、自動的にサーバからのレスポンスが引数として渡されます。関数の中でレスポンスを捕まえて、その text() メソッド、これは基本的にレスポンスを生のテキストで返すものを走らせます。これは XHR版の request.responseType = 'text' 部分と等価です。

text() もプロミスを返すので .then() を連鎖させ、その中で text() のプロミスが解決する生テキストを受け取るよう、関数を定義します。

Aside on promises

上の例のプロミスの構造を見直してみましょう。

fetch(url).then(function(response){
   response.text().then(function(text){
       poemDisplay.textContent = text;
   })
});

最初の行は「urlにあるリソースをとってこい」で、「それから(then) プロミスが解決したら指定した関数を実行しろ」です。

「解決」とは、「この先どこかの時点で、指定された処理の実行を終える」ことです。この場合だと”指定された処理とは指定のURLからリソースをとってきて、そのレスポンスを私たちがどうにかできるように返せ、です。

すぐには実行されないコードの塊で、未来のどこかの時点でレスポンスが返ってきたときに実行されます。

fetchを変数にしても動くし、

let myfetch = fetch(url);

myFetch.then(function(response){
   response.text().then(function(text){
       poemDisplay.textContent = text;
   })
});

.then() のレスポンスの引数は名前を付けることができます。

fetch(url).then(function (dogBiscuits) {
   dogBiscuits.text().then(function (text) {
       poemDisplay.textContent = text;
   });
});

レスポンスオブジェクトには text() メソッドがあって、これはレスポンスボディにある生データを受けて、プレーンテキストに変換します。このメソッドもプロミス(これは結果となるテキスト文字列で解決します)を返すので、ここでまた別の .then() を使い、この内部でテキスト文字列を使って私たちがやりたいことをおこなうための別の関数を定義します。

それぞれのブロックの結果を次のブロックに渡していくように、直接複数のプロミスブロック(.then() ブロック以外の種類もある)を次から次へと連鎖することができます。これがすごい。

fetch(url).then(function (response) {
   return response.text()
}).then(function (text) {
   poemDisplay.textContent = text;
});

多くの開発者はこの書き方をします。これはひとつ前のやつから順々に続いています。違うのは return 文を response.text() の前に書いて、それが出した結果を次チェーンに渡すようにしなければならない。

とりあえず、 return で返したものを .then で受け取って処理していくみたいなのがいいのかしら。

今日はここまで。明日例題やる。

この記事が気に入ったらサポートをしてみませんか?