aspidaのRestClientで多重送信を抑制する

OpenAPIでAPIが定義されているプロジェクトにおいて @aspida/fetch を使ってRestClientを生成・利用しています。

とあるGETリクエストを複数のコンポーネントからほぼ同時に呼び出す必要があり、リクエストの回数を1回にまとめたい状況がありました。
これをaspidaでやろうと思ったときにちょっと思ったようにできなかったのでメモ。

最初にやろうとした実装は、aspidaに渡すfetchをラップする方法。

const promises = {};
function customFetch(url, option) {
if (option.method === 'GET') {
const key = `GET__${url}`;
if (!promises[key]) {
promises[key] = fetch(url, option);
}
return promises[key];
} else {
return fetch(url, option);
}
}

promiseを再利用したいわけですが、こうすると、ResponseのStreamが使用済みなのでエラーになります。そりゃそうだ。

Response.clone() で複製してから使えばよいわけですが、aspidaの生成するtsコードで Response.json() を実行してしまうので、外からcloneを挟むようなことは無理そう…

色々考えた結果、こうなりました

const promises = {};
function dedupe(api, option) {
const key = `GET__${api.$path(option)}`;
if (!promises[key]) {
promises[key] = api.$get(option);
}
return promises[key];
}

使う側では

const result = await client.path.to.hoge.$get({ query: { fuga: 'piyo' } });

これを、

const result = await dedupe(client.path.to.hoge, { query: { fuga: 'piyo' } });

こうする。

関数で囲わなければいけなくなったのがちょっとスマートじゃないですが、まあ重複排除したいところだけ使えてポータブルな関数になったので良いということにしよう。

Google Publisher Tag のよくあるエラー

googletag.openConsole() で表示される警告文の意味と主な対処方法の自分メモ

用語

GPT: Google Publisher Tag
GAM: Google Ad Manager

ドキュメント

⚠️ 広告ユニットが取得されませんでした

何が起きているか

defineSlotは行われたが、displayやrefreshを行っておらず、広告リクエストが走っていない状態

対処方法

displayやrefreshを実行する。

googletag.display('div-id');
googletag.pubads().refresh([slot]);

disableInitialLoad() が利用されている場合は、displayでは広告リクエストが走らなくなるのでrefreshを使う。

⚠️ 広告ユニットが埋められませんでした

何が起きているか

配信条件に一致する広告申込情報が見つからずに広告を埋められなかった

対処方法

GAMで該当の広告ユニットと広告申込情報の配信設定やターゲティングを見直す