JavaScript

【Javascript】JavaScriptでAPIを実行する方法fetchとXMLHttpRequestの使い分けについて

今回は、JavaScriptから外部のAPIを実行するアプリを作成します。
JavaScriptでAPIを実行する仕組みとしては fetch と XMLHttpRequest があり、
fetch の方が一般的に推奨される方法となります。
動作確認としてGitHubの検索APIを利用しリポジトリ数を取得したいと思います。
GitHub APIの詳細についてはGitHub Docsを確認してください。

fetch と XMLHttpRequest の違い

簡単ではありますが、fetch と XMLHttpRequest の違いについてまとめてみました。
正直自分が実装する場合はあまり深く考えず、
動作環境の制約(古いブラウザ)があればXMLHttpRequestを使用し、
動作環境の制約が無ければfetchを使用するという感じで使い分けしています。
また、fetchのポリフィル(Polyfill)を利用すればfetch APIを古いブラウザでも利用できるようです。

fetch

仕組み
 PromiseベースのAPIであり、非同期操作をシンプルかつ直感的に扱うことができる。そのためソースコードの可読性が向上する。
動作環境
 幅広いブラウザでサポートされている。
拡張性
response.json() や response.text() などの便利なメソッドが提供されている。
ネットワークエラー対応
 Promiseチェーン内でエラーをキャッチしやすく、ネットワークエラーのハンドリングが容易。

XMLHttpRequest

仕組み
 コールバックベースで、複雑なコード構造が必要となる。
動作環境
 古いブラウザでサポートされており、環境制限がある場合には優位となる。
ネットワークエラー対応
 ステータスを条件に分岐させればハンドリングできる、

プログラム概要

①「確認」ボタンをクリックすることで、JavaScript関数の searchGitHub() を呼び出します。

<input type="text" id="searchword">
<input type="button" value="検索" onclick="searchGitHub()">

②各メッセージ項目の初期化と入力値を取得します。

// メッセージ初期化
document.getElementById("fetchMsg").innerHTML = "";
document.getElementById("xhrMsg").innerHTML = "";
var sysMsgElement = document.getElementById("sysMsg");
sysMsgElement.innerHTML = "";
sysMsgElement.style.color = "red";
sysMsgElement.style.display = "none";
// 入力値取得
var inputValue = document.getElementById("searchword").value;

③未入力の場合はエラーメッセージを表示し終了します。

if (inputValue == "") {
    sysMsgElement.style.display = "block";
    sysMsgElement.innerHTML = "未入力です";
    return;
}

④JavaScript関数の callapi_fetch() と callapi_xhr() 呼び出しに入力値を渡します。

callapi_fetch(inputValue);
callapi_xhr(inputValue);

[callapi_fetch概要]
⑤入力値を基にURLを作成し、GETリクエストを送信します。

var apiUrl = "https://api.github.com/search/repositories?q=" + inputValue;
// GETリクエストを送信
fetch(apiUrl)

⑥問題がなければfetchMsgに対して結果(total_count)を入力します。

.then(data => {
    document.getElementById("fetchMsg").innerHTML = "[fetch処理]: " + inputValue + "のリポジトリ総数は、" + data.total_count + "件です。";
})

[callapi_xhr概要]
⑦入力値を基にURLを作成し、GETリクエストを送信します。

// XMLHttpRequestオブジェクト作成
var xhr = new XMLHttpRequest();
// リクエスト設定(メソッド、URL、非同期フラグ設定)
xhr.open("GET", "https://api.github.com/search/repositories?q=" + inputValue, true); // 
// リクエスト送信
xhr.send();

⑧問題がなければ戻り値が文字列のためJSON形式に変換します。

var responseText = xhr.responseText;
var jsonData = JSON.parse(responseText);

⑨JSONから結果(total_count)を取得しxhrMsgに入力します。

document.getElementById("xhrMsg").innerHTML = "[XMLHttpRequest処理]: " + inputValue + "のリポジトリ総数は、" + jsonData.total_count + "件です。";

ソースコード

<html>
<head>
    <title>ボタンクリックイベント</title>
</head>
<body>
<h1>JavaScriptからのAPI実行</h1>
<p>GitHubの総リポジトリ数を検索します。<br>検索キーワードを入力してください。</p>
<input type="text" id="searchword">
<input type="button" value="検索" onclick="searchGitHub()">
<p id="sysMsg" style="display:none;"></p>
<p id="fetchMsg"></p>
<p id="xhrMsg"></p>

<!-- JavaScriptのコード -->
<script>
    function searchGitHub() {
        // メッセージ初期化
        document.getElementById("fetchMsg").innerHTML = "";
        document.getElementById("xhrMsg").innerHTML = "";
        var sysMsgElement = document.getElementById("sysMsg");
        sysMsgElement.innerHTML = "";
        sysMsgElement.style.color = "red";
        sysMsgElement.style.display = "none";
        // 入力値取得
        var inputValue = document.getElementById("searchword").value;
        // 未入力判定
        if (inputValue == "") {
            sysMsgElement.style.display = "block";
            sysMsgElement.innerHTML = "未入力です";
            return;
        }
        callapi_fetch(inputValue);
        callapi_xhr(inputValue);
    }

    function callapi_fetch(inputValue) {
        var apiUrl = "https://api.github.com/search/repositories?q=" + inputValue;
        // GETリクエストを送信
        fetch(apiUrl)
            .then(response => {
                // レスポンスが正常に受信された場合
                if (response.ok) {
                    return response.json(); // JSONデータを取得
                } else {
                    throw new Error('APIリクエストに失敗しました。');
                }
            })
            .then(data => {
                // レスポンスデータを処理
                console.log(data.total_count);
                document.getElementById("fetchMsg").innerHTML = "[fetch処理]: " + inputValue + "のリポジトリ総数は、" + data.total_count + "件です。";
            })
            .catch(error => {
                // エラーハンドリング
                console.error(error);
            });
    }

    function callapi_xhr(inputValue) {
        // XMLHttpRequestオブジェクト作成
        var xhr = new XMLHttpRequest();
        // リクエスト設定(メソッド、URL、非同期フラグ設定)
        xhr.open("GET", "https://api.github.com/search/repositories?q=" + inputValue, true); // 
        // リクエスト送信
        xhr.send();
        // レスポンス処理
        xhr.onreadystatechange = function () {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    // 戻り値は文字列
                    var responseText = xhr.responseText;
                    try{
                        var jsonData = JSON.parse(responseText);
                        console.log(jsonData.total_count);
                        document.getElementById("xhrMsg").innerHTML = "[XMLHttpRequest処理]: " + inputValue + "のリポジトリ総数は、" + jsonData.total_count + "件です。";
                    } catch (error) {
                        console.error('JSONパースエラー:', error);
                    }
                } else {
                    // エラーハンドリング
                    console.error('Request failed with status:', xhr.status);
                }
            }
        };
    }
</script>
</body>
</html>

サンプル

See the Pen CallAPI by alunote (@alunote) on CodePen.

まとめ

JavaScriptからAPIを呼び出し方法はいくつかありますが、迷った場合はfetchを選択すれば良いかと思います。
JavaScriptからAPIを実行できれば、ウェブページやウェブアプリケーションを動的に更新したり、入力項目に対する入力補助などパフォーマンスの向上ができるかと思います。ユーザーエクスペリエンスの向上やデータの活用が可能になり、豊かなウェブアプリケーションを開発できるのではないでしょうか。

説明は以上となります。
この記事が誰かの助けになれば幸いです。