11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

jQuery ではなくFetchAPIを使用してAJAX通信をおこなう

Last updated at Posted at 2023-11-30

はじめに

昔はブラウザ間の互換性に問題があったため、互換性を解決してくれるjQueryがはやりました。
が時代がたつとブラウザ間の互換性は解決され、dom操作も簡単にできるようになりました。
またフレームワーク(Angular,Vue.js,React)が登場しバージョン間の問題もあり新規でjQueryを導入するメリットがなくなってきました。
そのため脱JQueryに向け、よく使用されていると思われるAJAX通信をjavascriptのFetch APIに置き換えるための基本的な使い方をメモとして残します。

単純な例

jsonを返す単純なphpを用意

json_test.php
<?php
// テスト用
sleep(3);
?>
{"foundation": "Mozilla", "model": "box", "week": 45, "transport": "car", "month": 7}

fetchを使用して呼び出し

test.html
ajax_test();

function ajax_test() {
    fetch("./json_test.php")
        .then(response => {
            return response.json();
        })
        .then(json => {
            console.log(json);
        });
}

thenをチェーンメソッドでつなげ
最初のthenでjsonを受け取りデコード
jsonの結果を次のthenでコンソールに出力

async、awaitを使用した例

単純な例では非同期で行っていたが、async、awaitを使用することにより
プロミスを返す関数の処理を待機させ直列で動作(同期っぽく)させることができる。

test.html
    async_ajax_test();

    async function async_ajax_test() {
        const response = await fetch("./json_test.php");
        const json = await response.json();
        console.log(json);
    }

関数にasyncを付けfetchをするときにawaitをして処理を待機させる。
詳しい事は下記が参考になります。
https://qiita.com/jun1s/items/ecf6965398e00b246249

上記だけだとわかりづらいので例

最初に用意したjsonを返す単純なphpをsleepしないバージョン

json_test2.php
{"foundation": "Mozilla", "model": "box", "week": 45, "transport": "car", "month": 7}

非同期で呼び出し

test.html
ajax_test();
ajax_test2();

function ajax_test() {
    fetch("./json_test.php")
        .then(response => {
            console.log(1);
            return response.json();
        })
        .then(json => {
            console.log(2);
        });
}

function ajax_test2() {
    fetch("./json_test2.php")
        .then(response => {
            console.log(3);
            return response.json();
        })
        .then(json => {
            console.log(4);
        });
}

コンソールの結果

3
4
1
2

sleepが入っているjson_test.phpの結果が後から帰ってくるため順番が逆になっている

async、awaitを使用した呼び出し

test.html
async_ajax_test();

async function async_ajax_test(){
    const response = await fetch("./json_test.php");
    console.log(1);
    const json = await response.json();
    console.log(2);

    console.log(3);
    const response2 = await fetch("./json_test2.php");
    const json2 = await response2.json();
    console.log(4);
}

コンソールの結果

1
2
3
4

json_test.phpにsleepが入っているが、json_test.phpの結果をawaitにより待っているため
実行順序通りになっている

エラー処理

非同期時

test.html
ajax_test();

function ajax_test() {
    fetch("./json_test.php")
        .then(response => {
            if (!response.ok) {
                // httpステータス200以外でも入ってくるので200以外ならばエラーを投げる
                console.error(`status = ${response.status}, error = ${response.statusText}`);
                throw new Error(response.statusText);
            }
            return response.json();
        })
        .then(json => {
            console.log(json);
        }).catch(error => {
            // ネットワーク通信に失敗したとき
            console.error(error);
    });
}

httpステータス200以外でもthenに入ってくるのでresponse.okで判定し、ネットワークエラー時はcatchで拾う

async、awaitを使用した時

test.html
async_ajax_test();

async function async_ajax_test() {
    try {
        const response = await fetch("./json_test.php");
        const json = await response.json();
        console.log(json);
    } catch (err) {
        console.error(err);
    }
}

await使用時はtry catchで囲む

ajax通信を途中で中止したい場合

AbortControllerを使用する

test.html
<button id="abort_fetch">中断</button>
中断ボタンを用意する

const controller = new AbortController();
const signal = controller.signal;

ajax_test();

function ajax_test() {
    fetch("./json_test.php", {signal: signal})
        .then(response => {
            if (!response.ok) {
                // httpステータス200以外でも入ってくるので200以外ならばエラーを投げる
                console.error(`status = ${response.status}, error = ${response.statusText}`);
            }
            return response.json();
        })
        .then(json => {
            console.log(json);
        }).catch(error => {
            if (error.name === 'AbortError') {
                console.log('中断しました。');
                return
            }

            // ネットワーク通信に失敗したとき
            console.error(error.message);
    });
}

let abort_fetch = document.getElementById('abort_fetch');
abort_fetch.addEventListener('click', function() {
    controller.abort();
});

コンソールの結果

中断しました。

非同期処理を中断できるAbortControllerのシグナルオブジェクトを生成し、
fetchの第2引数にsignalオプションを指定します。
イベントリスナーでabort()を呼び出すことでフェッチを中断することができます。

詳しい解説は下記を参考に
https://developer.mozilla.org/ja/docs/Web/API/AbortController/signal

リクエスト時のオプション

fetch apiのデフォルトのメソッドはGETだがPOSTで送信したいときは
fecthの第2引数にオプションを指定する。

post_test.php
<?php
var_dump($_POST);
?>
test.html
ajax_test();

function ajax_test() {
    let form = new FormData()
    form.append('nama', 'test')

    fetch("./post_test.php",
        {
            method: "POST",
            body: form
        }
        ).then(response => {
            return response.text();
        })
        .then(test => {
            console.log(test);
        });
}

コンソールの結果

array(1) {
  ["nama"]=>
  string(4) "test"
}

fetchメソッドの第2引数のオプションにmethodに"POST"を指定してbodyにFormDataオブジェクトを指定する

その他のオプションに関しては下記にて
https://developer.mozilla.org/ja/docs/Web/API/fetch

まとめ

脱JQueryに向け、よく使用されるであろうajaxをFetchApiで実装する例を羅列してみました。
今回紹介したのは基本的な使い方のみでしたが、移行するきっかけになれば幸いです。
Fetchはまだまだ色々な機能がありますのでぜひとも使いこなしてください。

11
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?