ServiceWorkerGlobalScope: fetch 事件

Baseline 已廣泛支援

此功能已成熟,可跨多種裝置和瀏覽器版本工作。它自 ⁨2018 年 4 月⁩ 起已在所有瀏覽器中可用。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

注意:此功能僅在 Service Workers 中可用。

ServiceWorkerGlobalScope 介面的 fetch 事件在主應用程式執行緒發出網路請求時,在 Service Worker 的全域性作用域中觸發。它允許 Service Worker 攔截網路請求併發送自定義響應(例如,從本地快取)。

此事件不可取消,也不會冒泡。

語法

在諸如 addEventListener() 之類的方法中使用事件名稱,或設定事件處理程式屬性。

js
addEventListener("fetch", (event) => { })

onfetch = (event) => { }

描述

當主應用程式執行緒發出網路請求時,fetch 事件在 Service Worker 的全域性作用域中觸發。這不僅包括主執行緒中顯式的 fetch() 呼叫,還包括瀏覽器在頁面導航後加載頁面和子資源(如 JavaScript、CSS 和影像)的隱式網路請求。

事件處理程式會接收一個 FetchEvent 物件,該物件提供對請求的訪問,請求是一個 Request 例項。

FetchEvent 還提供了一個 respondWith() 方法,該方法接受一個 Response(或解析為 ResponsePromise)作為引數。這使得 Service Worker 事件處理程式能夠提供返回給主執行緒請求的響應。

例如,Service Worker 可以返回:

  • Cache 介面檢索到的本地快取響應。
  • Service Worker 使用諸如 Response.json() 等方法或 Response() 建構函式合成的響應。
  • 使用 Response.error() 方法的網路錯誤。這將導致 fetch() 呼叫被拒絕。

對於給定的請求,respondWith() 方法只能呼叫一次。如果添加了多個 fetch 事件監聽器,它們將按照註冊順序呼叫,直到其中一個呼叫了 respondWith()

respondWith() 方法必須同步呼叫:也就是說,你不能在 then 處理程式中呼叫它。

通常,fetch 事件處理程式會根據請求的特徵(如其 URL)執行不同的策略。

js
function strategy1() {
  return fetch("picnic.jpg");
}

function strategy2() {
  return Response.error();
}

const pattern1 = /^\/salamander/;
const pattern2 = /^\/lizard/;

self.addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  if (pattern1.test(url.pathname)) {
    event.respondWith(strategy1());
  } else if (pattern2.test(url.pathname)) {
    event.respondWith(strategy2());
  }
});

如果在處理程式中未呼叫 respondWith(),則使用者代理會自動發出原始網路請求。例如,在上面的程式碼中,所有不匹配 pattern1pattern2 的請求都像 Service Worker 不存在一樣發出。

事件型別

一個 FetchEvent

示例

快取後備網路

fetch 事件處理程式首先嚐試在快取中查詢響應。如果找到響應,則返回快取的響應。否則,它嘗試從網路獲取資源。

js
async function cacheThenNetwork(request) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    console.log("Found response in cache:", cachedResponse);
    return cachedResponse;
  }
  console.log("Falling back to network");
  return fetch(request);
}

self.addEventListener("fetch", (event) => {
  console.log(`Handling fetch event for ${event.request.url}`);
  event.respondWith(cacheThenNetwork(event.request));
});

僅快取

fetch 事件處理程式對指令碼和樣式表實現“僅快取”策略。如果請求的 destination 屬性為 "script""style",則處理程式僅在快取中查詢,如果未找到響應則返回錯誤。所有其他請求都將透過網路。

js
async function cacheOnly(request) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    console.log("Found response in cache:", cachedResponse);
    return cachedResponse;
  }
  return Response.error();
}

self.addEventListener("fetch", (event) => {
  if (
    event.request.destination === "script" ||
    event.request.destination === "style"
  ) {
    event.respondWith(cacheOnly(event.request));
  }
});

規範

規範
Service Workers
# dom-serviceworkerglobalscope-onfetch

瀏覽器相容性

另見