MENU

GASのfetchAllで複数APIの応答を整理する

当ページのリンクには広告(PR)が含まれていることがあります。
GASのfetchAllで複数APIの応答を整理する。複数のURL、fetchAll、応答を対応付けの処理例。

複数のAPIを呼ぶとき、1つが429、もう1つが200だった結果を、まとめて「失敗」とすると原因を追えません。GASのfetchAllで受け取った応答は、要求ごとの名前とHTTPコードを組にして整理します。

一度に渡す件数を増やせば問題が解決するわけではありません。利用先の制限とGASの割当があり、要求全体が例外で終わる場合もあります。最初は少数の読み取り要求に絞り、応答を受け取れた場合の失敗と、通信自体の失敗を分けます。

目次

要求の名前とURLを先にそろえる

公式のUrlFetchAppでは、fetchAllへURLや要求オブジェクトの配列を渡し、各入力要求に対するHTTPResponseの配列を受け取ります。結果を独自に完了順へ並べ替えず、要求の配列の位置と対応させます。

以下はJSONを返す読み取り用エンドポイントを想定し、例独自の上限を5件にしています。URLやキーがログへ広がらないよう、結果に出す識別名はcatalog・stockのような短い名前へ分けます。

例のURLは説明用です。実際に試すときは、自分が利用を認められた読み取り用URLへ置き換え、認証や取得頻度の条件を確認してください。投稿や送信を伴う要求は入れません。

HTTP失敗とJSON解析失敗を分けるコード

muteHttpExceptions:trueにより、HTTPの失敗コードも応答として整理する指定を入れます。通信の例外は外側へ返し、全部成功したような空配列へ置き換えません。

function inspectFetchAll(targets, fetchAll) {
  if (!Array.isArray(targets) || targets.length < 1 || targets.length > 5) {
    throw new Error('要求は1〜5件で指定してください');
  }
  const requests = targets.map(function (target) {
    if (!target.key || !/^https:\/\//.test(target.url)) throw new Error('要求名とHTTPS URLを確認');
    return {url: target.url, method: 'get', muteHttpExceptions: true};
  });
  const responses = fetchAll(requests);
  if (responses.length !== targets.length) throw new Error('応答件数を確認してください');
  return responses.map(function (response, index) {
    const code = response.getResponseCode();
    let validJson = false;
    try { JSON.parse(response.getContentText()); validJson = true; }
    catch (error) { /* 本文全体はログへ出しません。 */ }
    return {key: targets[index].key, httpStatus: code,
      okHttp: code >= 200 && code < 300, validJson: validJson};
  });
}

function previewFetchAllStatus() {
  const targets = [
    {key: 'catalog', url: 'https://example.com/catalog'},
    {key: 'stock', url: 'https://example.com/stock'}
  ];
  console.log(JSON.stringify(inspectFetchAll(targets,
    requests => UrlFetchApp.fetchAll(requests))));
}

架空のcatalog応答が200でJSON、stock応答が429でJSONなら、前者はokHttp:true、後者はfalseで、validJsonは両方trueです。200でもHTMLが返ればvalidJson:falseになります。HTTP成功と、必要な形式のデータが返ったことは別の判定です。

まとめて例外になった場合

通信そのものが例外になれば、上の関数は結果一覧を返さず止まります。どの要求まで相手へ到達したかを、空の一覧から推測しないようにします。特に更新を伴う要求を後から追加すると、全件再送で重複する可能性があります。

読み取り要求でも、再試行の回数と待機条件は決めておきます。429が1件だけなら、その要求の制限や応答ヘッダーを確認し、正常な要求まで無条件に取り直さないようにします。HTTPResponseの項目は公式資料で確認できます。

件数を増やす前に見ること

JSONとして解析できても、業務で必要な項目や件数がそろうことまでは分かりません。APIごとのデータ形式を検査する段階を、この結果の確認後に置きます。今回の関数は応答状況を見分けるところまでです。

ローカルでは代用fetchAllで、200と429の混在、不正JSON、応答数の違い、通信例外、上限超過を確認しました。実APIへの通信や同時実行速度は計測していません。設定値はPropertiesService、失敗した実行はGASのエラーログで確認する構成にできます。

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次