app-template/packages/adsense/src/loader.ts

71 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { AdSensePushCommand } from "./types.js";
const SCRIPT_MARKER = "adsbygoogle.js";
let scriptPromise: Promise<void> | null = null;
let scriptClient: string | null = null;
function findExistingScript(adClient: string): HTMLScriptElement | null {
for (const el of Array.from(document.scripts)) {
if (el.src.includes(SCRIPT_MARKER) && el.src.includes(adClient)) {
return el;
}
}
return null;
}
/**
* 加载 Google AdSense 官方脚本(幂等)。
* - 仅浏览器环境生效,SSR 中为 no-op
* - 同一 adClient 复用同一 Promise;已在页面中的脚本会被识别并跳过
*/
export function loadAdSense(adClient: string): Promise<void> {
if (typeof document === "undefined") {
return Promise.resolve();
}
if (scriptPromise) {
if (scriptClient === adClient) {
return scriptPromise;
}
return Promise.reject(
new Error(
`[adsense] 脚本已按 client=${scriptClient} 加载,不支持同时加载多个发布商 ID`,
),
);
}
const existing = findExistingScript(adClient);
if (existing) {
scriptClient = adClient;
scriptPromise = Promise.resolve();
return scriptPromise;
}
scriptClient = adClient;
scriptPromise = new Promise<void>((resolve, reject) => {
const script = document.createElement("script");
script.async = true;
script.crossOrigin = "anonymous";
script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${encodeURIComponent(adClient)}`;
script.onload = () => resolve();
script.onerror = () => {
// 失败必须重置状态,否则后续调用会一直复用 rejected Promise 无法重试
scriptPromise = null;
scriptClient = null;
script.remove();
reject(new Error("[adsense] AdSense 脚本加载失败"));
};
document.head.appendChild(script);
});
return scriptPromise;
}
/** 向队列 push 一条命令,触发对已挂载 <ins class="adsbygoogle"> 的渲染。 */
export function pushAdSense(command: AdSensePushCommand = {}): void {
if (typeof window === "undefined") {
return;
}
window.adsbygoogle ??= [];
window.adsbygoogle.push(command);
}