Skip to content

ブラウザの API クライアントと非同期処理を読み解く ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.8.1

$p.apiGet() などの関数は、API に JSON を POST し、jqXHR を返すラッパーです。通常の画面送信用 $p.ajax() のように、応答を dispatch へ渡したり、フォームの送信バッファを自動収集したりはしません。

API の対応表は API ラッパー、このページでは実装と結果の受け取り方を扱います。

apiUrl とラッパーの担当 ​

apiUrl(id, action, controller) は #ApplicationPath と引数を連結します(URL 生成)。

指定作るパスの形
controller なしapi/items/id/action
controller と真と評価される idapi/controller/id/action
controller あり、id が偽と評価される値api/controller/action

URL エンコードや引数の妥当性検証をする処理ではありません。apiGet などは args.id を読み、URL を作って apiExec へ渡します。apiExec の args 省略対応は、apiGet の args 省略対応を意味しません。 apiGet() はその前に args.id を読むため、引数が必要です(レコードのラッパー、共通実行)。

apiExec がすること・しないこと ​

処理実装
data の既定値args.data が undefined なら空オブジェクト
TokenHidden の #Token が1件なら data.Token へ追加。元のオブジェクトも変わる
本文JSON.stringify(data)
HTTP メソッドpost。apiGet も HTTP GET ではない
応答の型dataType は json
Content-TypeURL が api/ に一致する条件なら application/json
結果$.ajax の jqXHR を返し、done・fail・always を登録

根拠は apiExecです。dataType は応答の解析指定であり、リクエストの Content-Type とは別です。この経路は $p.ajax を呼ばないため、before_send・CAPTCHA 前処理・dispatch・フォームの ControlId 削除なども呼びません。一方、$.ajaxSetup の共通設定は $.ajax に適用されます(画面送信との比較、画面送信本体)。

読み取り結果を受け取る例 ​

以下はブラウザ側のスクリプトです。閲覧できる既存レコードの編集画面で、ブラウザコンソールから実行します。応答の形を決め打ちせず、API から受け取った JSON を確認する読み取り例です。

js
(function () {
    const id = $p.id();
    if (!Number.isFinite(id) || id <= 0) {
        console.warn('読み取るレコード ID がありません。');
        return;
    }
    $p.apiGet({
        id: id,
        data: {},
        done: function (response) {
            console.log('API の応答', response);
        },
        fail: function (xhr, status, error) {
            console.warn('API の通信失敗', xhr.status, status, error);
        },
        always: function () {
            console.log('API の通信終了');
        }
    });
})();

done は jqXHR の通信成功に対応します。保存・業務処理の成功判定や、返却データの項目確認は API の応答に合わせて別に行います。返却形式は ApiVersion の決まり方も確認してください。

Promise として待つ例 ​

同じ読み取りを async 関数で待つ場合は、返された jqXHR を await します。通常の $p.send() の即時の数値とは違います。

js
(async function () {
    const id = $p.id();
    if (!Number.isFinite(id) || id <= 0) return;
    try {
        const response = await $p.apiGet({ id: id, data: {} });
        console.log('API の応答', response);
    } catch (xhr) {
        console.warn('API の通信失敗', xhr.status);
    }
})();

async の指定はグローバル設定を変える ​

args.async が undefined でなければ、apiExec は $.ajaxSetup({ async: args.async }) を実行します。リクエスト個別の設定に async を入れたり、呼び出し後に設定を戻したりする実装ではありません(設定変更)。

例えば { async: false } を渡すと、その後に明示的な指定をしない他の jQuery Ajax にも影響する共通設定が残ります。読み取り例は async を渡さず、この変更を行いません。$p.ajax はリクエスト個別に async を指定するため、この点でも API ラッパーと違います(個別指定)。

一括削除は通常の apiExec とも違う ​

apiBulkDelete は apiBulkDeleteExec へ進みます。ここでは args.data.GridCheck を読み、真なら一覧の選択状態から All と Selected を data へ追加します(一括削除)。

  • GridCheckAll が真なら、GridUnCheckedItems を除外側の ID 一覧として使う。
  • それ以外は GridCheckedItems を選択側の ID 一覧として使う。
  • data を省略した場合に備えるコードより先に args.data.GridCheck を読むため、data オブジェクトを用意する必要がある。
  • この経路には、通常の apiExec の Content-Type 設定と cache の明示がない。

選択状態のキーが必要な経路を、任意の画面から呼べる削除関数として扱わず、一覧の状態と要求するデータを確認します。このページの実行サンプルには削除処理を含めません。

独立したデバウンスを持つ例 ​

入力から API 検索へつなぐ場合、本体の $p.debounce は全呼び出しでタイマーを共有し、自動ポストバックの Enter 送信にも使われます。自作処理には別のタイマーを用意します(共通タイマー、本体での利用)。

次はブラウザコンソール用の、独立した予約関数の例です。通信はせず、最後の呼び出しだけを実行する仕組みを試します。

js
(function () {
    let timer;
    const schedule = function (action, delay) {
        clearTimeout(timer);
        timer = setTimeout(action, delay);
    };
    schedule(function () { console.log('最初'); }, 100);
    schedule(function () { console.log('最後'); }, 100);
})();

100 ms 後に 最後 だけを出します。API 検索へ応用するときは、通信の応答順も別に管理します。タイマーで開始回数を減らすことと、先に開始した通信の結果を後から採用しないことは別の制御です。

検証範囲と関連ページ ​

URL・要求設定・データの変更・jqXHR の受け取りと掲載コードは、本体 JavaScript と模擬通信で確認しています。実サーバーでの権限・API 応答・保存処理は未検証です。

変更履歴

第1版フロント基盤JSのイベント・通信・日時処理を詳しく解説