JavaScript を使用して、サーバーと通信する方法について学習します。

通信には 同期通信非同期通信 があります。

同期通信は簡単に言うと aタグで他の画面に移動するような処理で、画面が表示されるまでユーザーの操作が制限されます。

非同期通信はバックグラウンドで通信を行うため、ユーザーの操作が制限されません。

ここでは、非同期通信について学習します。

Sync and Async(同期通信と非同期通信)

JavaScript を使用して 外部のサービスや自社サーバーと通信したい場合があります。

具体的には、商品を検索したり、SNSの「いいね」ボタンを押したりするような場合です。

同期通信を行う場合は、HTMLの form タグにデフォルトである action属性 と method属性 を使用して 画面そのものを再度リクエスト することで対応ができます。
しかし、この方法だと、画面の更新処理が発生するためサイトの利便性が落ちてしまいます

「いいね」ボタンを押すたびに、画面すべてに更新が掛かってしまうようなサービスは誰も求めないからです。

「いいね」を押したら、画面のいいねマークの色を変え、「いいね」を押したとサーバーに通信すればいいだけです。

下記のボタンは、それぞれ同期通信非同期通信のデモです。

「JSを使用しない(同期通信)のいいねボタン」と「JSを使用した(非同期通信)のいいねボタン」があります。それぞれ違いを試してみてください。

「いいね」ボタンのような小さなアクションに、画面の更新処理は大げさに感じたと思います。

このような場合は、JavaScriptの非同期通信でサーバーと通信した結果から画面の一部分だけを更新 します。

Web API とは

API(Application Programming Interface)とは、サービスのデータや仕組みを外部と連携するための仕組みのことです。

この通信に HTTP(http, https)を使用する API のことを Web API といいます。

例えば、https://rabico.dev/owner/profile *1 に リクエストすれば、サーバーがオーナーのプロフィールデータを返却する といったものになります。
※1 実際には返却されません

つまり、この Web API を使用すれば、バックエンド(サーバー)とフロントエンド(ブラウザ)間でデータ通信を行い、様々なサービスを提供することが出来るようになります

この Web API を使用してサービスの機能を公開しているものも多くあります。

Web API を用いたサービスの例

Youtube Data API

Youtube のAPI(Youtube Data API)を使用すれば、YoutubeのWebサイトにある機能(動画・再生リスト・チャンネルの検索、更新)を自分のWebサイトで使用することが出来るようになります。
* JavaScriptでリクエスを行い使用します。

 

LINE Messaging API

LINE のAPI(Messaging API)を使用すれば LINEで自動返信を行うbot(ボット)を作ることができます。
*バックエンドでリクエストURLに応じたレスポンスを返す仕組みを公開し使用します。

同期通信と非同期通信

通信には、同期通信非同期通信 があります。

同期通信

リクエストを行ってレスポンスが返ってくるまで一切の処理を行うことができません。そのため、必ずレスポンスを受け取った後に実行する必要がある処理などは、同期通信を用います。
また、レスポンスがあるまで一切の処理が行えないので、画面がフリーズしたように感じることがあります。
例: ページ遷移など

非同期通信

リクエストを行ってレスポンスが返ってくるまでの間も、他の処理を行うことができます。レスポンスが返ってきた場合に、実行する コールバック関数 を作成することによって、レスポンスを受け取ったときの処理を設定することができます。
リクエスト中も画面で動作を行うことが出来るため、ユーザー体験(エクスペリエンス)が向上します。そのため、多くのサービスで非同期通信が使用されています

例: Google Mapなど

Ajax(XMLHttpRequest API) と Fetch API

JavaScript で 非同期通信 を行うための方法として、Ajax と Fetch があります。

Ajax は 1999年から採用されているため、多くのサービスで使用されています。歴史が古いということもあり、成熟した非同期通信方法です。しかし、Ajax のコードは少し複雑です。

代わりに近年では Fetch が使用され始めました。この Fetch は 2020年現在のところ完璧に Ajax に変わる手段ではありませんが、Ajax に必要だった複雑なコードをより簡潔に書くことができます。

そのため、最近の多くのサービスでこの Fetch を使用しています。

IE は Fetch に 対応していないため、Polyfill という外部のコードを使用する必要があります。

Fetch の Polyfill

Ajaxの例


// 新しい XMLHttpRequest インスタンスを作成します
let xhr = new XMLHttpRequest();
xhr.open( 'GET', 'https://demo.com' ); // リクエスト方法, リクエスト先のURL

// リクエストの状態が変更したときに実行されるコールバック関数を設定します
xhr.onreadystatechange = function() {

    // リクエストの状態で 4 以外は未完了のため、終了します
    // https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/readyState
    if ( xhr.readyState !== 4 ) return;

    if ( xhr.status === 200 ) {
        // リクエストのレスポンスコードが 200(OK) 
        const jsObject = JSON.parse( xhr.responseText );  // レスポンス結果(JSON)を JSオブジェクトに変換します
        console.log( jsObject );                          // jsObjectを コンソールに出力します
    }
    else {
        // リクエストのレスポンスコードが 200以外(OKではない) 
        console.log( 'HTTP error', xhr.status, xhr.statusText );
    }
};

// リクエストを開始します(open していないと実行できません)
xhr.send();
                

より詳しい XMLHttpRequest については、HTTP XMLHttpRequest – Web API | MDN でご確認いただけます。

Fetchの例


fetch( 'https://demo.com', { method: 'GET' })   // リクエスト先のURL, リクエスト方法などのオプション
    .then( response => response.json() )        // レスポンス結果(JSON)を JSオブジェクト に変更します
    .then( jsObject => console.log(jsObject) )          // jsObjectを コンソールに出力します
    .catch( error => console.error('error:', error) );  // エラーの場合は コンソールに出力します
                

より詳しい Fetch については、Fetch を使う – Web API | MDN でご確認いただけます。

試してみる

実際に Fetch を使用して リクエストを試してみましょう。

以下の REQ | RES というサイトでは、Web APIのデモを試すことができます。

Reqres – A hosted REST-API ready to respond to your AJAX requests

LIST USERS (https://reqres.in/api/users?page=1)を使用してユーザーのリストを取得してみます。

page 数は 2 まであるみたいです。

Ajaxを試してみる

「Ajaxでリクエストする」ボタンを押すと、1ページ目のユーザーリストをリクエストし、返ってきた結果を コンソール に表示します。


<button onclick="_onClickAjaxReqButton(event);">Ajaxでリクエストする</button>
                

function _onClickAjaxReqButton(e) {
    _readUsersByAjaxAnd(1); // 1ページ目のデータを読み込みます
}

function _readUsersByAjaxAnd(pageNum) {
    pageNum = pageNum || 1; // pageNumが空であれば 1 を初期値にします
    // 新しい XMLHttpRequest インスタンスを作成します
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://reqres.in/api/users?page=' + pageNum); // リクエスト方法, リクエスト先のURL

    // リクエストの状態が変更したときに実行されるコールバック関数を設定します
    xhr.onreadystatechange = function() {

        // リクエストの状態で 4 以外は未完了のため、終了します
        // https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/readyState
        if (xhr.readyState !== 4) return;

        if (xhr.status === 200) {
            // リクエストのレスポンスコードが 200(OK) 
            const jsObject = JSON.parse(xhr.responseText);  // レスポンス結果のJSONを JSオブジェクトに変換します
            console.log(jsObject);                          // jsObjectを コンソールに出力します
        }
        else {
            // リクエストのレスポンスコードが 200以外(OKではない) 
            console.log('HTTP error', xhr.status, xhr.statusText);
        }
    };

    // リクエストを開始します
    xhr.send();
}
                
Ajaxデモ


        

Fetchを試してみる

「Fetchでリクエストする」ボタンを押すと、1ページ目のユーザーリストをリクエストし、返ってきた結果を コンソール に表示します。


<button onclick="_onClickFetchReqButton(event);">Fetchでリクエストする</button>
                

function _onClickFetchReqButton(e) {
    _readUsersByFetchAnd(1);
}

function _readUsersByFetchAnd(pageNum) {
    pageNum = pageNum || 1; // pageNumが空であれば 1 を初期値にします
    fetch( 'https://reqres.in/api/users?page=' + pageNum, { method: 'GET' })   // リクエスト先のURL, リクエスト方法などのオプション
        .then( response => response.json() )        // レスポンス結果(JSON)を JSオブジェクト に変更します
        .then( jsObject => console.log(jsObject) )          // jsObjectを コンソールに出力します
        .catch( error => console.error('error:', error) );  // エラーの場合は コンソールに出力します
}
                
Fetchデモ

        

HTTPメソッド

このHTTPメソッドを設定することで、サーバーは そのリクエストが 何をしてほしいのかを判断して処理を行うことができます。

htmlformタグ には method という属性があり、ここには GET もしくは POST を設定することができますが、Ajax や Fetch では他にもいくつかの HTTPメソッド を使用することができます

ここでは特に利用する代表的なものを紹介します。

メソッド名 リクエストの意味
GET リソース(データの検索結果など)を取得したい
POST リソースを新しく作成(保存)してほしい
PUT リソースを更新してほしい
DELETE リソースを削除してほしい

その他の HTTPリクエストメソッド については、HTTP リクエストメソッド – HTTP | MDN でご確認いただけます。

HTTPステータスコード

Google 404 page

レスポンスには HTTPステータスコード というレスポンスの結果が数値で設定されています。

Ajax を使用した場合は、XMLHttpRequest.status とすることで参照することができ、Fetch を使用した場合は、Response.status とすることで参照することができます。

このコードをもとに、リクエストが成功したか、失敗したかを判断することが可能になります。

ステータスコード 意味
2xx(Success) 200番台は、リクエストが成功し、レスポンスが正常に返されたことを意味します
3xx(Redirection) 300番台は、リクエストを完了させるために、他に処理が必要であることを意味します
4xx(Client Error) 400番台は、リクエストに誤りがあったことを意味します
5xx(Server Error) 500番台は、サーバーでエラーが起きたことを意味します

より詳しい HTTPステータスコード については、HTTPステータスコード – Wikipedia でご確認いただけます。

JSON(JavaScript Object Notation)

JSON はテキストの記法です。

JavaScript の オブジェクト と書き方がよく似ていて、オブジェクト と テキスト(文字列) で相互に変換することができます。

そのため JSON でデータを通信することで、JavaScript でデータを扱うことが容易になります。

JSON 以外では、XML やHTML などがありますが、JavaScript を使用したデータ通信の多くは JSON が使用されます。

JavaScriptのオブジェクト


{
    id: 1,
    name: '仲野伸行',
    profile: 'プログラミングスクールRAKUMAの代表'
}
            

JSON


{
    "id": 1,
    "name": "仲野伸行",
    "profile": "RAKUMAオンラインスクールの代表"
}
            

JSオブジェクト と JSON の違い

JavaScriptオブジェクト

キーは('')や("")で囲まず、値が文字列の場合は('')または("")で囲みます。

JSON

キーは("")で囲み、値が文字列の場合は("")で囲みます。

JSオブジェクト と JSON の相互変換

JSON は テキストの記法 なので、通常は文字列として扱われます

この JSON 記法 で作成された文字列を、JavaScriptのオブジェクトに変換したり、逆に オブジェクト を JSON に変換することができます。

JSON => JavaScriptオブジェクト


let json = '{"id": 1, "name": "仲野伸行", "profile": "プログラミングスクールRAKUMAの代表"}';
console.log('JSON文字列', json);
let jsObject = JSON.parse(json);
console.log('JavaScriptオブジェクトに変換しました', jsObject);
            

JavaScriptオブジェクト => JSON


json = JSON.stringify(jsObject);
console.log('JSON文字列に変換しました', json);
            

課題

JavaScript で Web API を利用する場合のメリットは何ですか?

説明してください。

同期通信 と 非同期通信 の違いは何ですか?

説明してください。

Ajax を使用し、REQ | RES の SINGLE USER( https://reqres.in/api/users/2 )に GET リクエストを行ってください。

取得した JSON を コンソール に 出力して確認しください。

Fetch を使用し、REQ | RES の SINGLE USER( https://reqres.in/api/users/2 )に GET リクエストを行ってください。

取得した JSON を コンソール に 出力して確認しください。

HTTPメソッド にはどのような役割がありますか?

説明してください。

HTTPステータスコード にはどのような役割がありますか?

説明してください。