Window: fetchLater() 方法

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

實驗性: 這是一項實驗性技術
在生產中使用此技術之前,請仔細檢查瀏覽器相容性表格

Window 介面的 fetchLater() 方法建立了一個延遲抓取。

fetchLater() 請求會在頁面導航離開(頁面被銷燬或進入 bfcache),或者在提供的 activateAfter 超時後傳送——以先發生者為準。

fetchLater() 方法返回一個 FetchLaterResult 物件,其中包含一個 activated 值,表示請求是否已傳送。請注意,該方法不返回實際抓取的結果(因為它通常在文件被銷燬後傳送),並且抓取的整個響應,包括正文和標頭,都會被忽略。

請求主體為 ReadableStream 的請求無法被延遲。

fetchLater() 方法由 connect-src 內容安全策略指令控制,而不是由檢索到的資源的指令控制。

語法

js
fetchLater(resource)
fetchLater(resource, options)

引數

fetchLater() 方法接受與 fetch() 相同的所有引數,但增加了一個 activateAfter 選項。

resource

這定義了您希望抓取的資源。與 fetch() 相同,這可以是

  • 一個字串或任何其他具有 stringifier 的物件——包括一個 URL 物件——它提供您要抓取的資源的 URL。URL 可以相對於基本 URL,在視窗上下文中,基本 URL 是文件的 baseURI
  • 一個 Request 物件。
options 可選

一個 DeferredRequestInit 物件,其中包含您要應用於請求的任何自定義設定,包括一個 activateAfter 超時值,它定義了結果在傳送前應延遲多長時間。

異常

fetch() 的相同異常可能會針對 fetchLater() 丟擲,以及以下附加異常

QuotaExceededError

由於超出可用配額,此功能的使用被阻止。有關更多詳細資訊,請參閱 fetchLater() 配額fetchLater() 的呼叫者幾乎在所有情況下都應保持防禦性並捕獲 QuotaExceededError 錯誤,尤其是當他們嵌入第三方 JavaScript 時。

RangeError DOMException

當指定負 activateAfter 值時丟擲。

TypeError DOMException

除了 fetch() 的原因外,此異常還會針對 ReadableStream 請求(無法延遲)或使用不可信 URL(例如 http://)時丟擲。

返回值

一個 FetchLaterResult,其中包含一個 activated 布林屬性,指示請求是否已傳送。

注意:一旦抓取請求傳送,其響應——包括主體和標頭——將不可用並被忽略。

示例

fetchLater() 配額文章提供了配額如何應用的示例。

GET 請求延遲到頁面導航離開或關閉

js
fetchLater("/send_beacon");

POST 請求延遲約一分鐘

在此示例中,我們建立一個 Request,並提供一個 activateAfter 值以將請求傳送延遲 60,000 毫秒(或一分鐘)

js
fetchLater("/send_beacon", {
  method: "POST",
  body: getBeaconData(),
  activateAfter: 60000, // 1 minute
});

注意:實際傳送時間未知,因為瀏覽器可能會等待更長或更短的時間,例如為了最佳化延遲抓取的批處理。

透過 try/catch 將 POST 請求延遲約一分鐘

與上述示例相同,但最佳實踐是將其封裝在 try/catch 中

js
try {
  fetchLater("/send_beacon", {
    method: "POST",
    body: getBeaconData(),
    activateAfter: 60000, // 1 minute
  });
} catch (e) {
  if (e instanceof QuotaExceededError) {
    // Handle the quota error
  } else {
    // Handle other errors
  }
}

POST 請求延遲約一分鐘並建立一個函式來檢查是否已傳送

js
const result = fetchLater("https://report.example.com", {
  method: "POST",
  body: JSON.stringify(myReport),
  activateAfter: 60000 /* 1 minute */,
});

function checkIfFetched() {
  return result.activated;
}

更新待處理請求

在此示例中,我們使用 AbortController 取消並重新建立請求

js
let beaconResult = null;
let beaconAbort = null;

function updateBeacon(data) {
  const pending = !beaconResult || !beaconResult.activated;
  if (pending && beaconAbort) {
    beaconAbort.abort();
  }

  createBeacon(data);
}

function createBeacon(data) {
  if (beaconResult && !beaconResult.activated) {
    // Avoid creating duplicated beacon if the previous one is still pending.
    return;
  }

  beaconAbort = new AbortController();
  beaconResult = fetchLater({
    url: data,
    signal: beaconAbort.signal,
  });
}

無效示例

以下任何對 fetchLater() 的呼叫都將丟擲

js
// Only potentially trustworthy URLs are supported
fetchLater("http://untrusted.example.com");

// The length of the deferred request has to be known
fetchLater("https://origin.example.com", { body: someDynamicStream });

// Deferred fetching only works on active windows
const detachedWindow = iframe.contentWindow;
iframe.remove();
detachedWindow.fetchLater("https://origin.example.com");

規範

規範
Fetch
# deferred-fetch

瀏覽器相容性

另見