JavaScriptのXHRの送り方いろいろ: XMLHttpRequest, fetch, async/await

目次

JavaScriptのXHR(XMLHttpRequest)の送り方は1つだけではありません。モダンなXHRに向けてそれぞれのHTTPリクエストの送り方を比較・検討してみます。

前提

  • jQuery, superagent, axiosなどのAJAX系ライブラリは使用しないこととする。
  • 検証に使うブラウザは最新版のChrome (現在はVersion56.0)
  • 今回リクエストを送る先は仮想的に下記のURLとする
var url = "https://your.domain.net/"

1. XMLHttpRequest

さぁ,まずは古き良きXMLHttpRequest。ローレベルなAPIでAJAX処理が書きにくいのですが、歴史がある分多くのブラウザで動作します。

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
  console.log(xhr.status);
};
xhr.onerror = function() {
  console.log("error!");
};
xhr.send();

Chrome Dev Toolのコンソールで動かしてみましょう。

xhr1

モダンな書き方にしてみよう!

このまま次のXHRに進んでも良いですがせっかくなので上記のコードをもう少しモダンにしてみます。

今回は下記の2つの書き方を導入します。

上記の2つで1のXMLHttpRequestのコードを書き直すとこのようになります。

const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => {
  console.log(xhr.status);
};
xhr.onerror = () => {
  console.log("error!");
};
xhr.send();

varconstに、function=>へと変更しています。わかりやすくなってスッキリしましたね。

この書き方でも動くかChrome Dev Toolのコンソールで動かしてみましょう。

xhr2

:ok: でした。

2. fetch API

次はfetch APIを使ってXHRしてみましょう。ちなみにfetch APIはChrome Version 42よりサポートされています。

fetch(url).then((response) => {
  console.log(response.status);
}).catch(() => {
  console.log("error caught!");
});

コードとしてはurlをfetchしてthen, catchをチェインさせてそれぞれの処理内容を書いていくというものになります。

Chrome Dev Toolコンソールで動かした結果。

xhr3

fetchPromiseを返す点がポイントですね。

3. fetch + async/await

最後のXHRはasync/awaitになります。Chrome55からのサポートなので最近追加された機能ということになります。

さきほどのfetchのコードをasync/awaitの機能を使って書き換えてみましょう。

(async() => {
  try {
    const response = await fetch(url);
    console.log(response.status);
  } catch (e) {
    console.log("error!")
  }
})();

ポイントとしては asyncを使ってまず無名関数を作ります。これでその関数内にawaitを使う準備ができました。awaitはPromiseが返されるのを待機するので、先程のPromiseを返すfetch関数の手前にawaitを宣言します。これでfetch関数はthenでコールバックをチェインする必要がなくなり、response変数にダイレクトに結果が代入されます。エラー処理に関してはtryで処理内容を囲み、catchでエラーを補足します。

コンソールで動かしてみた結果は下記の通り。

xhr4

結論

結論としては現時点では3つめのfetch+async/awaitな書き方が最もモダンな書き方となります。

3の書き方でなにが嬉しいかというと:

  • 非同期処理でありがちなコールバック地獄からの解放
  • 同期的なコードで書けるので書きやすい・読みやすい
  • try~catch節を用いているのでエラー処理の見通しが良い

このあたりでしょうか。

まだasync/awaitシンタックスはECMAScript 2017のDraftな仕様というステータスであり現時点でIEはサポートしていない書き方です。なので多くの人が触る環境下のコードベースにおける導入は厳しいですが、これらが使える利用環境を限定できるのであれば積極的に使っていきたい書き方ですね。

(おまけ)babelで使う場合

babel で async/await のシンタックス使いたい場合はbabel-plugin-syntax-async-functionsを使うことになります。

Syntax async functions · Babel

参考