JavaScriptのXMLHttpRequestとPromiseの違い
JavaScriptのXMLHttpRequestとPromiseの違いについてまとめました。
Promiseの書き方は次の記事を参考にしてみてください。
XMLHttpRequestとPromiseの違い
JavaScriptでAJAX通信する方法は複数あります。
Promiseのメリットを示すために、AJAXでHTTPリクエストをする古いやり方を記述してみます。
今回はhttps://restcountries.eu/のWeb APIを活用します。
こちらが共通の関数とします。
const renderCountry = function (data) {
const html = `
<img class="country__img" src="${data.flag}" />
<h3 class="country__name">${data.name}</h3>
`; div.insertAdjacentHTML('beforeend', html);
XMLHttpRequestでの書き方(Callback hell)
const getCountryData = function(country) {
const getCountryAndNb = function (country) {
//AJAX call country 1
const request = new XMLHttpRequest();
request.open('GET', `https://restcountries.eu/rest/v2/name/${country}`);
request.send(); //リクエストを送ると、バックグランドでデータをフェッチしてきます。
//リクエストがロードされた次の処理を行う。
request.addEventListener('load', function () {
// データをとると、[{}]と配列の中にひとつのオブジェクトが入った形式になるので、分割代入で配列を取り除きます。
const [data] = JSON.parse(this.responseText); //this = request
//Render country 1
renderCountry(data);
//bordersという項目が隣接の国の数を表している
//2つ目の国は、一つの目の国のbordersの情報が必要なため、必ず後に取得される
// Get Neighbour country
const [neighbour] = data.borders; //配列になっているので、分割代入でとる
if (!neighbour) return;
const request2 = new XMLHttpRequest();
// https://restcountries.eu/rest/v2/alpha/{code}
request2.open(
'GET',
`https://restcountries.eu/rest/v2/alpha/${neighbour}`
);
request2.send(); //リクエストを送ると、バックグランドでデータをフェッチしてきます。
request2.addEventListener('load', function () {
//alphaは単純に配列ではない。今回はnameではなくalphaというcodeをサーチしていたので分割代入は不要。
const data2 = JSON.parse(this.responseText);
//Render country 2
renderCountry(data2);
});
});
};
getCountryAndNb('Japan');
このように、XMLHttpRequest()を変数に格納し、それにopen()メソッドでGETなどの取得方法とURLを指定します。
そして、send()メソッドでリクエストを送ると、バックグランドでデータをフェッチしてきます。
リクエストがロードされた次の処理を行うように、addEventListenerでloadイベントを設定します。
addEventListenerは第二引数にコールバック関数を取ります。
this.responseTextはJSONデータのフォーマットで送られてきます。JSONは基本的には大量の文字列の集まりのため、JavaScriptのオブジェクトに変換します。JSON.parse()を使います。
このaddEventListener('load’,コールバック関数)のコールバック関数の中にさらにaddEventListener('load’,コールバック関数)を入れてAJAXの順番を制御しています。このこと何層にもネストになるコールバック関数をCallback hellといいます。
Promiseでの書き方(Flat Promise chain)
const request3 = fetch('https://...url');
console.log(request3); //Promise
const getCountryData = function (country) {
fetch(`https://restcountries.eu/rest/v2/name/${country}`)
.then(function (
response
) {
console.log(response);
return response.json();
}).then(function(data) {
console.log(data);
renderCountry(data[0]);
})
};
getCountryData('Japan');
Promiseは、バックグランドでデータをフェッチするのに、XMLHttpRequestが三行必要なところを一行で行っています。
//XMLHttpRequestの場合3行
const request = new XMLHttpRequest();
request.open('GET', `https://restcountries.eu/rest/v2/name/${country}`); //ここにURLをいれる
request.send(); //リクエストを送ると、バックグランドでデータをフェッチしてきます。
//Promiseの場合1行
const request3 = fetch('https://restcountries.eu/rest/v2/name/japan');
fetch(https://restcountries.eu/rest/v2/name/${country}
)というのが、Promiseを返します。その返されたPromiseに、then()メソッドをチェーンして次の処理を記述することができます。then()メソッドの中にはコールバック関数を入れます。fulfilledの状態になったらどうしたいのかの処理を書きます。
たとえば、fetchされた上の中身を見ると、body: ReadableStreamという記述があります。これは、JSONでないと中身がみれません。
json()メソッドは、fetch()メソッドで返されたすべてのオブジェクト、結果の値で利用可能です。
json()メソッドも非同期の関数です。つまり、新しいpromiseを返します。そのため、returnする必要があります。
新しいpromiseというのは、次の部分がすべて新しいpromiseになります。
.then(function (
response
) {
console.log(response);
return response.json();
})
そのため、その新しいpromiseにさらにthen()メソッドでチェーンします。そして、データをコンソールに表示します。
このpromiseのチェーンはどれだけあってもつなげることができ、コールバック関数と違って、くの字にどんどんネストが深くなっていかないことから、Flat Promise chainなどと呼ばれています。
アロー関数でさらに簡潔に
ちなみに上のコードは、アロー関数を使って簡潔にかくと、次のようになります。
const request3 = fetch('https://restcountries.eu/rest/v2/name/japan');
console.log(request3); //Promise {}
const getCountryData = function (country) {
fetch(`https://restcountries.eu/rest/v2/name/${country}`)
.then( response => response.json())
.then(data => renderCountry(data[0]));
};
getCountryData('Japan');