ajaxまとめ(xhr, jquery, axios, fetch)

いやー2週間も穴を開けてしまいましたよ!いかんいかん!
おかげで頭の中は書きたいことだらけです!

さて今回はajaxということで、もうこれなしじゃ生きていけないくらいajaxは世に浸透していますね。
ajaxは本来「エイジャックス」と読むみたいですけど、どうしても私は「アジャックス」と読んでしまいます。

本来の意味はようわかりません。私は画面読み込み後に行われるHTTP Request(非同期処理)全般のことだと思っています。違ったらすみません。
本記事内ではこういう認識でお願いします。

その昔はajaxといえばxhr(XMLHttpRequest)かjqueryしかメジャーどころがなかったように思えますが、今はいろんな選択肢がありますね。

モダンブラウザ公式のWeb APIであるfetchやら、いつの間にか現れたaxiosやらとこの業界の流れの速さを思い知らされます。

さて、今回はこれらのHTTP Request送る系プログラムを改めて振り返りつつ、書き方の違いなどを見ていきましょう!

前提条件

リクエストはphpで作った以下のスーパー簡易エコーサーバーに向けて送信します。

<?php echo file_get_contents("php://input");
  • メソッドはPOST
  • Content-Type=application/x-www-form-urlencoded
  • ボディはtext=testtesttest

なので、絶対レスポンスはtext=testtesttestになります。

やってみる

まずはこんな画面を作ります。

それぞれのボタンを押せば先ほど定義したリクエストが投げられます。
そのレスポンステキストはボタンの下に表示されます。

当たり前ですが、どれを押しても同じレスポンスが得られます。

ソースコードはこちら

document.addEventListener('DOMContentLoaded', () => {
  const btnxhr = document.querySelector('#xhr')
  const btnjquery = document.querySelector('#jquery')
  const btnaxios = document.querySelector('#axios')
  const btnfetch = document.querySelector('#fetch')
  const result = document.querySelector('#result')

  // xhr
  btnxhr.addEventListener('click', evt => {
    console.log('xhr')
    const xhr = new XMLHttpRequest()
    xhr.open('post', 'index.php')
    xhr.onload = () => {
      result.innerHTML = xhr.responseText
    }
    xhr.send('text=testtesttest')
  })

  // jquery
  btnjquery.addEventListener('click', evt => {
    console.log('jquery')
    $.post('index.php', 'text=testtesttest', data => {
      result.innerHTML = data
    })
  })

  // axios
  btnaxios.addEventListener('click', evt => {
    console.log('axios')
    axios
      .post('index.php', 'text=testtesttest', {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      })
      .then(resp => {
        result.innerHTML = resp.data
      })
  })

  // fetch
  btnfetch.addEventListener('click', evt => {
    console.log('fetch')
    fetch('index.php', {
      method: 'post',
      body: 'text=testtesttest',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    })
      .then(e => e.text())
      .then(txt => {
        result.innerHTML = txt
      })
  })
})

xhr(XMLHttpRequest)

const xhr = new XMLHttpRequest()
xhr.open('post', 'index.php')
xhr.onload = () => {
  result.innerHTML = xhr.responseText
}
xhr.send('text=testtesttest')

おなじみですね。
インスタンスを生成して、openでメソッドと送り先を指定します。
sendでリクエストを送信するわけですが、xhrは送る前にonloadにレスポンスを処理するコールバック関数を設定します。

jquery

$.post('index.php', 'text=testtesttest', data => {
  result.innerHTML = data
})

xhrに比べて記述量は一気に減りましたね。
$.postの第一引数に送り先、第二にリクエストボディ、第三にレスポンスを処理するコールバック関数を指定します。
なんやかんや言ってjqueryは優秀ですわな。

axios

axios
  .post('index.php', 'text=testtesttest', {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  })
  .then(resp => {
    result.innerHTML = resp.data
  })

jqueryよりは記述量が多いですね。

axios.postの第一引数に送り先、第二引数にリクエストボディ、第三引数にリクエストヘッダなどの設定を指定します。この関数はPromiseを返します。
そのため、thenでつなげてレスポンスを処理するわけです。

axiosはデフォルトでリクエストのContent-Typeapplication/jsonになっています。今回は通常のフォーム送信を考えているので、リクエストヘッダの設定でContent-Typeを指定しています。

fetch

fetch('index.php', {
  method: 'post',
  body: 'text=testtesttest',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
})
  .then(e => e.text())
  .then(txt => {
    result.innerHTML = txt
  })

fetchでPOSTすることってあります?私は初めてやりました。
普段はaxiosを使っているので戸惑いましたね。
記述量は多いですね。

fetchの第一引数に送り先、第二引数にリクエストの内容を定めるオブジェクトを指定します。この関数はPromiseを返します。

fetchが返すレスポンスをどんな形で取得するかを最初のthenで選択します。
他にもjson()などがあります。

その次のthenで先ほど選択した形のレスポンスを取得できます。

別にContent-Typeは指定しなくても良かった気がしますが、一応ね。

個人的な感想

外部のパッケージを入れたくない人はxhrfetchの二択になりますね。
私も一時期、全ての処理をブラウザから与えられたAPIと自分の力だけで処理したいと思っていた時期があって、その頃はxhrを使っていました。
プログラマーって一度はそういう時期を過ごしますよね。
xhrfetchはコールバックが好きかPromiseかが好きかで分かれることでしょう。

便利なら外部のモノを使うっしょ!って人はjqueryaxiosを選ぶことでしょう。その中でもコールバック派かPromise派かでそれぞれ分かれますね。

コールバックかPromiseかって書いてますけど、コールバックの方でもPromiseを返すようなラッパーを作って使用してると思います。

例えばjqueryなら

new Promise(resolve =>
      $.post('index.php', 'text=testtesttest', resolve)
    ).then(e => {
      console.log('promise', e)
    })

みたいな感じでPromiseで包んであげるだけでPromise化できます。

どれ使っても結局一緒なんですけど、個人的には

  • 普段のリクエストはjsonで送る
  • Promise対応してる
  • 名前がかっこいい

の理由でaxiosを使っています。

おわりに

いつもボリューミーな記事を多く書いていたので、このくらいの方が読みやすいかなと思って今日はこのへんで。
やり始めるとアレもコレもって試してみたくなっちゃってだめですね笑

それでは次回にお会いしましょう!さらだばー!