今一度AJAX、HTTPなど通信系を整理しようと思う


フロントエンドエンジニアなので、業務でAPIとの接続は何度もやってきました。
ただ、この部分は基本APIが必要としてるデータを過不足なく渡して、レスポンスのJSONをもらって、コンポーネントで扱うというパターンが主流なので、ブラウザとサーバーとの間でどのような通信が行われているかの深い理解がなくてもなんとか実装できてしまう部分ではありました。

ですが、いい加減この辺りも理解しておかないとまずいと思ったので、記事にしました。

目次
・AJAX通信
・HTTP通信
・リクエストとレスポンス
・エラーハンドリング
・実例

AJAX通信とは?

Asynchronous JavaScript + XMLの略
Asynchronousは非同期という意味。Ajax最大の特徴はJavaScriptでクライアントとサーバー間のHTTP通信を「非同期」で行える事。サーバーからのレスポンス(元々XMLでしたが、今はJSONが主流)によって「動的にページの一部だけ書き換えるプログラミング手法のこと」です。というわけで、「複数の既存の機能」を組み合わせて実現しています。

では、AJAX通信する為の手段は?
・fetch API:JSの言語に組み込まれて、ライブラリ不要(この記事のサンプルコードはfetchを使います)
・AXIOS:外部ライブラリ
・XMLHttpRequest API:これもJSの言語に組み込まれて、ライブラリ不要。元々はこれだったけどもう古い。。

などがあり、現在はFetchとAXIOSの2択らしいです。

HTTP通信とは?

AJAXの中で触れた「HTTP通信」は何なのか?World Wide Web(ウェブ)は、クライアントとサーバーが、HTTP(Hypertext Transfer Protocol)という通信方法の約束事(プロトコル)に従い、データを送受信することで成り立っています。
要は、クライアントとサーバー間で通信をするときには、足並みを揃えましょうって事ですね。

フロントからサーバーへのリクエスト(HTTPのリクエストメソッド)は主なモノは以下4種類。
・GET:データの「取得」
・POST:データの「追加」DBへ登録
・PUT:データの「更新」
・DELETE:データの「削除」

リクエストとレスポンスとは?

クライアント(ブラウザ)がサーバーにリクエストを投げて、サーバーがレスポンスを返すというよく見かける図です。

クライアント(ブラウザ)のメイン機能
・HTMLビューワー
・サーバーと通信する(リクエストを投げてレスポンスを受け取り、描画を変える)

サーバーの機能
・クライアントからのリクエストを解釈し、処理を行ってレスポンス(HTMLかJSON)を返す

リクエストとは

サーバーへのHTTPリクエストには以下3つのパートがあります。
・HTTPリクエスト行
・HTTPヘッダー行
・HTTPボディ(データ本体がここに入る、GETの場合はつけられない)

リクエストボディ:
一番大事なサーバーに渡す「key, value 形式のデータ」をここに入れます。
(型やデータそのものに過不足があると当然エラーになる)
*GETメソッドでのリクエストの時は、これは付けられない。

リクエストパラメータ:
URLの最後に追加された値の事です。(?より後ろの部分)
例)https://www.youtube.com/watch?v=l_FAcYvmfXI
?以降が動画のIDですね。
*GETメソッドでのリクエストの時は、このパラーメーターしか付けません。

レスポンスとは

サーバーはクライアントから「HTTPリクエスト」を受けたら、処理を行い、「HTTPレスポンス」を返します。
サーバーからのHTTPレスポンスには以下3つのパートがあります。
・レスポンス状態行(よく聞くステータス状態が含まれる、200ならOK)
・HTTPヘッダー
・データ本体(ここにJSONやHTMLが入ります)

エラーハンドリング

HTTP通信ではエラーがつきもので、成功した場合の処理だけではなく、エラーの場合も想定した実装が必要です。それを一般的にエラーハンドリングと言います。(実際このエラーハンドリングに大した実装してないケースって結構ありますが。。)

例)
アップロードするのに規定外のファイルだった
 ↓
サーバーからエラーが返される
 ↓
エラーを受けて、ファイルが規定外だよとユーザーに教えてあげる処理を呼ぶ

他にも、一定時間レスポンスが来なければ、タイムアウトさせたりとか。。を実装せずひたすら純粋に待ち続ける処理しか実装してないケースもあったりします。。

またJSONが空なのにステータスコードが200が来てしまうといったAPI側のバグも想定しておくなど、このレスポンスハンドリングは結構注意が必要な所だと思います。。

実例

前置きが長くなりました、いよいよ実例を見ていきましょう。

    try {
      fetch('http://example.com/movies.json')
        .then(response => response.json())
        .then(data => console.log(data));

    } catch (error) {
      console.log('error:', error);
    }

これはAPIにGETメソッドでリクエストして、データを取得するだけの処理です。
*fetchメソッドではGETの場合、メソッドを省略してもOKですが、本来は↓です。

fetch('http://example.com/movies.json', {method: 'GET'})

POST,PUT,DELETEなどサーバーにdataを送ってリクエストする場合は、こんな感じです。(これはMDNから引用)
一番下のbodyにDBに保存するデータが含まれます。

  const response = await fetch(url, {
    method: 'POST', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    redirect: 'follow', // manual, *follow, error
    referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    body: JSON.stringify(data) // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります
  })

補足

AJAX通信をローカルで行うにはローカルサーバーが必要です。http-serverとかが簡単に導入できて便利だと思います。

まだまだ基本を整理したに過ぎないので、新たな学びがあれば追記、修正していきます。