Skip to content

Commit 31ba9f6

Browse files
tunethewebgithub-actions[bot]chrisdavidmills
authored
Document fetchLater() (#39016)
* Fetch Later API * More updates * Rename api * Add quotas docs * Tweaks * Cleanup * Linting fix * Linting fix * Update PP docs * Fix folder name * Fix example * Linting fixes * More linting fixes * Tweak * Explain example * More linting * Add CSP and more exception details * Update files/en-us/web/api/window/fetchlater/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/api/window/fetchlater/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/api/window/fetchlater/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/api/window/fetchlater/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * more quota examples * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Review feedback * Accepting first batch of review feedback Co-authored-by: Chris Mills <[email protected]> * Second batch of suggestions from code review Co-authored-by: Chris Mills <[email protected]> * Update files/en-us/web/api/fetchlater_api/index.md Co-authored-by: Chris Mills <[email protected]> * Update files/en-us/web/api/fetchlater_api/index.md * Update files/en-us/web/api/fetchlater_api/index.md * Update files/en-us/web/api/fetchlater_api/index.md * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md * Update files/en-us/web/api/fetchlater_api/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md * Update files/en-us/web/api/window/fetchlater/index.md * Review feedback * Update files/en-us/web/api/fetchlaterresult/activated/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Rename file * Meta cleanup * Tweaks * browser-compat for deferred-fetch and deferred-fetch-init * Permissions Policy updates * Apply suggestions from code review Co-authored-by: Chris Mills <[email protected]> * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md * Review feedback * KB -> KiB * Permissions Policy BCD fixes * Frontmatter * Fetch Interfaces * Update files/en-us/web/api/deferredrequestinit/index.md Co-authored-by: Chris Mills <[email protected]> * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md Co-authored-by: Chris Mills <[email protected]> * Update files/en-us/web/api/fetchlater_api/fetchlater_quotas/index.md Co-authored-by: Chris Mills <[email protected]> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Chris Mills <[email protected]>
1 parent 57b01b6 commit 31ba9f6

File tree

12 files changed

+812
-1
lines changed

12 files changed

+812
-1
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
title: DeferredRequestInit
3+
slug: Web/API/DeferredRequestInit
4+
page-type: web-api-interface
5+
status:
6+
- experimental
7+
browser-compat: api.Window.fetchLater
8+
---
9+
10+
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}}
11+
12+
The **`DeferredRequestInit`** dictionary of the [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) represents the set of options that can be used to configure a deferred fetch request.
13+
14+
The `DeferredRequestInit` object is passed directly into the {{domxref("window.fetchLater()")}} function call as the second argument.
15+
16+
## Instance properties
17+
18+
This dictionary extends the {{domxref("RequestInit")}} dictionary with the addition of the following properties:
19+
20+
- `activateAfter` {{optional_inline}}
21+
22+
- : A {{ domxref("DOMHighResTimeStamp") }} indicating a timeout in milliseconds after which the fetch request should be sent. The fetch can be sent earlier on navigating away. The _actual_ sending time is unknown, as the browser may wait for a longer or shorter time, for example, to optimize the batching of deferred fetches. If the `activateAfter` property is not provided, the deferred fetch waits until the end of the page visit (including entering the [bfcache](/en-US/docs/Glossary/bfcache)).
23+
24+
### Exceptions
25+
26+
- `RangeError` {{domxref("DOMException")}}
27+
- : Raised when a negative `activateAfter` is provided.
28+
29+
## Examples
30+
31+
### Defer a `GET` request until the page is destroyed or enters the bfcache
32+
33+
In this example, no `DeferredRequestInit` object is provided and no timeout is used:
34+
35+
```js
36+
fetchLater("/send_beacon");
37+
```
38+
39+
### Defer a `POST` request for around 1 minute
40+
41+
In this example we create a {{domxref("Request")}}, and provide an `activateAfter` value to delay sending the request for 60,000 milliseconds (or one minute):
42+
43+
```js
44+
fetchLater({
45+
url: "/send_beacon"
46+
method: "POST"
47+
body: getBeaconData(),
48+
}, {activateAfter: 60000 /* 1 minute */});
49+
```
50+
51+
> [!NOTE]
52+
> The actual sending time is unknown, as the browser may wait for a longer or shorter period of time, for example to optimize batching of deferred fetches.
53+
54+
## Specifications
55+
56+
{{Specifications}}
57+
58+
## See also
59+
60+
- [Using Fetch](/en-US/docs/Web/API/Fetch_API/Using_Fetch)
61+
- [ServiceWorker API](/en-US/docs/Web/API/Service_Worker_API)
62+
- [HTTP access control (CORS)](/en-US/docs/Web/HTTP/Guides/CORS)
63+
- [HTTP](/en-US/docs/Web/HTTP)

files/en-us/web/api/fetch_api/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ You can create a request and response directly using the {{DOMxRef("Request.Requ
2323

2424
Find out more about using the Fetch API features in [Using Fetch](/en-US/docs/Web/API/Fetch_API/Using_Fetch).
2525

26-
## Fetch Interfaces
26+
## Interfaces
2727

2828
- {{domxref("Window.fetch()")}} and {{domxref("WorkerGlobalScope.fetch()")}}
2929
- : The `fetch()` method used to fetch a resource.
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
---
2+
title: fetchLater() quotas
3+
slug: Web/API/fetchLater_API/fetchLater_quotas
4+
page-type: guide
5+
status:
6+
- experimental
7+
browser-compat:
8+
- http.headers.Permissions-Policy.deferred-fetch
9+
- http.headers.Permissions-Policy.deferred-fetch-minimal
10+
---
11+
12+
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}}
13+
14+
Deferred [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API) fetches are batched and sent once the tab is closed. At this point, there is no way for the user to abort them. To avoid situations where documents abuse this bandwidth to send unlimited amounts of data over the network the API sets quotas on how much data can be deferred to be sent later.
15+
16+
These quotas can be managed through {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} and {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} [Permissions Policy](/en-US/docs/Web/HTTP/Guides/Permissions_Policy) directives.
17+
18+
## Overview
19+
20+
The overall quota for `fetchLater()` is 640KiB per document. By default, this is divided into a 512KiB top-level quota and a 128KiB shared quota:
21+
22+
- The 512KiB top-level quota by default is for any `fetchLater()` requests made from the top-level document and direct subframes using that origin.
23+
- The 128KiB shared quota by default is for any `fetchLater()` requests made in cross-origin subframes (for exmaple, `<iframe>`s, `<object>`s, `<embed>`s, and`<frame>`s).
24+
25+
`fetchLater()` requests can be made to any URL and are not restricted to the same origin as the document or the subframe, so it's important to differentiate between requests made in the top-level document content (whether to first-party or third-party origins) and those made in subframes.
26+
27+
For example, if a top-level `a.com` document includes a `<script>` that makes a `fetchLater()` request to `analytics.example.com`, this request would be bound by the top-level 512KiB limit. Alternatively, if the top-level document embeds an `<iframe>` with a source of `analytics.example.com` that makes a `fetchLater()` request, that request would be bound by the 128KiB limit.
28+
29+
## Quota limits by reporting origin and subframe
30+
31+
Only 64KiB of the top-level 512KiB quota can be used concurrently for the same reporting origin (the request URL's origin). This prevents third-party libraries from reserving quota opportunistically before they have data to send.
32+
33+
Each cross-origin subframe gets an 8KiB quota out of the shared 128KiB quota by default, allocated when the subframe is added to the DOM (whether `fetchLater()` will be used in that subframe or not). This means that, in general, only the first 16 cross-origin subframes added to a page can use `fetchLater()` as they will use up the 128KiB quota.
34+
35+
## Increasing subframe quotas by sharing the top-level quota
36+
37+
The top-level origin can give selected cross-origin subframes an increased quota of 64KiB, taking it out of the larger top-level 512KiB limit. It does this by listing those origins in the {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} Permissions Policy directive. This is allocated when the subframe is added to the DOM, leaving less quota for the top-level document and direct same-origin subframes. Multiple same-origin subdomains can each get a 64KiB quota.
38+
39+
## Restricting the shared quota
40+
41+
The top-level origin can also restrict the 128KiB shared quota to named cross-origin subframes by listing those origins in the {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} Permissions Policy. It can also revoke the entire 128KiB default subframe quota and instead keep the full 640KiB quota for itself and any named `deferred-fetch` cross-origins by setting the {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} Permissions Policy to `()`.
42+
43+
## Delegating quotes to subframes of subframes
44+
45+
By default, subframes of subframes are not allocated a quota and so cannot use `fetchLater()`. Subframes allocated the increased 64KiB quota can delegate the full 64KiB quota to further subframes and allow them to use `fetchLater()` by setting their own `deferred-fetch` Permissions Policy. They can only delegate their full quota to further subframes, not parts of it, and cannot specify new quotas. Subframes using the minimal 8KiB quota cannot delegate quotas to subframes. To be delegated quota, sub-subframes must be included in both the top-level and the subframe `deferred-fetch` {{httpheader('Permissions-Policy')}} directives.
46+
47+
## When quotas are exceeded
48+
49+
When quotas are exceeded, a `QuotaExceededError` is thrown when the {{domxref('Window.fetchLater()','fetchLater()')}} method is called to initiate the deferred request.
50+
51+
Permissions Policy checks are not discernable from quota checks. Calling `fetchLater()` will throw a `QuotaExceededError` both if the quota is actually exceeded and if the quota was restricted for that origin via a Permissions Policy.
52+
53+
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript.
54+
55+
## Examples
56+
57+
### Using up the minimal quota
58+
59+
```http
60+
Permissions-Policy: deferred-fetch=(self "https://b.com")
61+
```
62+
63+
1. A `<iframe src="https://b.com/page">` receives 64KiB upon being added to the top-level document, from the top-level's 512KiB limit.
64+
2. A `<iframe src="https://c.com/page">` is not listed and so receives 8KiB upon being added to the top-level document from the 128KiB shared limit.
65+
3. 15 more cross-origin iframes would each receive 8KiB upon being added to the top-level document (similar to `c.com`).
66+
4. The next cross-origin iframe would not be granted any quota.
67+
5. If one of the cross-origin iframes is removed, its deferred fetches will be sent.
68+
6. The next cross-origin iframe _would_ receive an 8KiB quota, as there is quota available again.
69+
70+
### RevokiRestricting the minimal quota to named origins
71+
72+
```http
73+
Permissions-Policy: deferred-fetch-minimal=("https://b.com")
74+
```
75+
76+
1. `<iframe src="https://b.com/page">` receives 8KiB upon being added to the top-level document.
77+
2. `<iframe src="https://c.com/page">` receives no quota upon being added to the top-level document.
78+
3. The top-level document and its same-origin descendants can use up to 512KiB.
79+
80+
### Revoking the minimal quota altogether with top-level exceptions
81+
82+
```http
83+
Permissions-Policy: deferred-fetch=(self "https://b.com")
84+
Permissions-Policy: deferred-fetch-minimal=()
85+
```
86+
87+
1. `<iframe src="https://b.com/page">` receives 64KiB upon being added to the top-level document.
88+
2. `<iframe src="https://c.com/page">` receives no quota upon being added to the top-level document.
89+
3. The top-level document and its same-origin descendants can use up to the full 640KiB but that is reduced to 574KiB if a `b.com` subframe is created (or even less if multiple `b.com` subframes are created, each of which will be allocated a 64KiB quota).
90+
91+
### Revoking the minimal quota altogether with no exceptions
92+
93+
```http
94+
Permissions-Policy: deferred-fetch-minimal=()
95+
```
96+
97+
1. The top-level document and its same-origin descendants can use up the full 640KiB.
98+
2. Subframes are not allocated any quota and cannot use `fetchLater()`.
99+
100+
### Same-origin subframes share quota with the top-level and can delegate to subframes
101+
102+
Assuming a top-level document on `a.com`, which embeds a subframe of `a.com`, which embeds a subframe of `b.com`, and no explicit Permission Policies.
103+
104+
1. The top-level document of `a.com` has the default 512KiB quota.
105+
2. `<iframe src="https://a.com/embed">` shares the 512KiB quota upon being added to the top-level document.
106+
3. `<iframe src="https://b.com/embed">` receives an 8KiB quotaupon being added to the top-level document.
107+
108+
### Same-origin subframes canot share quota with the top-level when separated by a cross-origin subframe
109+
110+
Assuming a top-level document on `a.com`, which embeds a `<iframe src="https://b.com/">`, which embeds a subframe of `<iframe src="https://a.com/embed">`, and no explicit Permission Policies.
111+
112+
1. The top-level document of `a.com` has the default 512KiB quota.
113+
2. `<iframe src="https://b.com/">` shares the 8KiB quota.
114+
3. `<iframe src="https://a.com/embed">` receives no quota; even though this is same-origin with the top origin, it is separated by a cross-origin.
115+
116+
### Secondary subframes of subframes do not get quota by default
117+
118+
Assuming a top-level document on `a.com`, which embeds a `<iframe src="https://b.com/">`, which embeds a `<iframe src="https://c.com/">`, and no explicit Permission Policies.
119+
120+
1. The top-level frame of `a.com` has the default 512KiB quota.
121+
2. `<iframe src="https://b.com/">` receives 8KiB of the default shared quota.
122+
3. `<iframe src="https://c.com/">` receives no quota.
123+
124+
### Granting the full quota to a further subframe
125+
126+
Assuming a top-level document on `a.com`, which embeds a `<iframe src="https://b.com/">`, which embeds a `<iframe src="https://c.com/">`.
127+
128+
Assuming that `a.com` has the following Permissions Policy:
129+
130+
```http
131+
Permissions-Policy: deferred-fetch=("https://c.com" "https://c.com")
132+
```
133+
134+
And, assuming that `b.com` has the following Permissions Policy:
135+
136+
```http
137+
Permissions-Policy: deferred-fetch=("https://c.com")
138+
```
139+
140+
1. The top-level frame of `a.com` has the default 512KiB quota.
141+
2. `<iframe src="https://b.com/">` receives 64KiB of the default quota.
142+
3. `<iframe src="https://b.com/">` delegates its full quota of 8KiB to `c.com`. `b.com` cannot use `fetchLater()`.
143+
4. `<iframe src="https://c.com/">` receives 8KiB of quota.
144+
145+
### Redirects do not transfer quota
146+
147+
Assuming a top-level document on `a.com`, which embeds a `<iframe src="https://b.com/">`, which redirects to `c.com`, and no explicit top-level Permission Policies.
148+
149+
1. The top-level frame of `a.com` has the default 512KiB quota.
150+
2. `<iframe src="https://b.com/">` receives 8KiB of the default shared quota.
151+
3. The 8KiB is not transferred to `c.com` when `<iframe src="https://b.com/">` redirects to there, but the 8KiB is not released.
152+
153+
### Redirects of subframes back to the top-level origin allow use of the top-level quota
154+
155+
Assuming a top-level document on `a.com`, which embeds a `<iframe src="https://b.com/">`, which redirects to `a.com`, and no explicit top-level Permission Policies.
156+
157+
1. The top-level frame of `a.com` has the default 512KiB quota.
158+
2. `<iframe src="https://b.com/">` receives 8KiB of the default shared quota.
159+
3. The 8KiB is not transferred to `a.com` when `<iframe src="https://b.com/">` redirects to there, but it is able to share the full top-level quota again, and the 8KiB is released.
160+
161+
### Examples which throw a `QuotaExceededError`
162+
163+
```js
164+
// Maximum of 64KiB per origin
165+
fetchLater(a_72_kb_url);
166+
167+
// Maximum of 64KiB per origin including headers
168+
fetchLater("https://origin.example.com", { headers: headers_exceeding_64kb });
169+
170+
// Maximum of 64KiB per origin including body and headers
171+
fetchLater(a_32_kib_url, { headers: headers_exceeding_32kib });
172+
173+
// Maximum of 64KiB per origin including body
174+
fetchLater("https://origin.example.com", {
175+
method: "POST",
176+
body: body_exceeding_64_kib,
177+
});
178+
179+
// Maximum of 64KiB per origin including body and automatically added headers
180+
fetchLater(a_62_kib_url /* with a 3kb referrer */);
181+
```
182+
183+
### Examples which eventually throw a `QuotaExceededError`
184+
185+
In the following sequence, contained in the top-level document, the first two requests would succeed, but the third would throw. That's because, even though the overall 640KiB quota was not exceeded, the third request exceeds the reporting-origin quota for `https://a.example.com` and would throw.
186+
187+
```js
188+
fetchLater("https://a.example.com", { method: "POST", body: a_40kb_body });
189+
fetchLater("https://b.example.com", { method: "POST", body: a_40kb_body });
190+
fetchLater("https://a.example.com", { method: "POST", body: a_40kb_body });
191+
```
192+
193+
## Specifications
194+
195+
{{Specifications}}
196+
197+
## Browser compatibility
198+
199+
{{Compat}}
200+
201+
## See also
202+
203+
- [`fetchLater()` API](/en-US/docs/Web/API/fetchLater_API)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: fetchLater() API
3+
slug: Web/API/fetchLater_API
4+
page-type: web-api-overview
5+
status:
6+
- experimental
7+
browser-compat: api.Window.fetchLater
8+
---
9+
10+
{{DefaultAPISidebar("fetchLater API")}}{{SeeCompatTable}}
11+
12+
The **`fetchLater()` API** provides an interface to request a deferred fetch that can be sent after a specified period of time, or when the page is closed or navigated away from.
13+
14+
## Concepts and usage
15+
16+
Developers often need to send (or beacon) data back to the server, particularly at the end of a user's visit to a page — for example, for analytics services. There are several ways to do this: from adding 1 pixel {{HTMLElement("img")}} elements to the page, to {{domxref("XMLHttpRequest")}}, to the dedicated {{domxref("Beacon API", "Beacon API", "", "nocode")}}, and the {{domxref("Fetch API", "Fetch API", "", "nocode")}} itself.
17+
18+
The issue is that all of these methods suffer from reliability problems for end-of-visit beaconing. While the Beacon API and the {{domxref("Request.keepalive", "keepalive")}} property of the Fetch API will send data, even if the document is destroyed (to the best efforts that can be made in this scenario), this only solves part of the problem.
19+
20+
The other — more difficult — part to solve concerns deciding _when_ to send the data, since there is not an ideal time in a page's lifecycle to make the JavaScript call to send out the beacon:
21+
22+
- The {{domxref("Window.unload_event", "unload")}} and {{domxref("Window.beforeunload_event", "beforeunload")}} events are unreliable, and outright ignored by several major browsers.
23+
- The {{domxref("Window.pagehide_event", "pagehide")}} and {{domxref("document.visibilitychange_event", "visibilitychange")}} events are more reliable, but still have issues on mobile platforms.
24+
25+
This means developers looking to reliably send out data via a beacon need to do so more frequently than is ideal. For example, they may send a beacon on each change, even if the final value for the page has not yet been reached. This has costs in network usage, server processing, and merging or discarding outdated beacons on the server.
26+
27+
Alternatively, developers can choose to accept some level of missing data — either by:
28+
29+
- Beaconing after a designated cut-off time and not collecting later data.
30+
- Beaconing at the end of the page lifecycle but accepting that sometimes this will not be reliable.
31+
32+
The `fetchLater()` API extends the {{domxref("Fetch API")}} to allow setting fetch requests up in advance. These deferred fetches can be updated before they have been sent, allowing the payload to reflect the latest data to be beaconed.
33+
34+
The browser then sends the beacon when the tab is closed or navigated away from, or after a set time if specified. This avoids sending multiple beacons but still ensures a reliable beacon within reasonable expectations (i.e., excluding when the browser process shuts down unexpectedly during a crash).
35+
36+
Deferred fetches can also be aborted using an {{domxref("AbortController")}} if they are no longer required, avoiding further unnecessary costs.
37+
38+
### Quotas
39+
40+
Deferred fetches are batched and sent once the tab is closed; at this point, there is no way for the user to abort them. To avoid situations where documents abuse this bandwidth to send unlimited amounts of data over the network, the overall quota for a top-level document is capped at 640KiB.
41+
42+
Callers of `fetchLater()` should be defensive and catch `QuotaExceededError` errors in almost all cases, especially if they embed third-party JavaScript.
43+
44+
Since this cap makes deferred fetch bandwidth a scarce resource, which needs to be shared between multiple reporting origins (for example, several RUM libraries) and subframes from multiple origins, the platform provides a reasonable default division of this quota. In addition, it provides {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}} and {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}} [Permissions Policy](/en-US/docs/Web/HTTP/Guides/Permissions_Policy) directives to allow dividing it differently when desired.
45+
46+
See [fetchLater() quotas](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for more details and examples.
47+
48+
## Interfaces
49+
50+
- {{domxref("Window.fetchLater()")}}
51+
- : Used to queue a resource for sending at a later point.
52+
- {{domxref("DeferredRequestInit")}}
53+
- : Represents the set of options that can be used to configure a deferred fetch request.
54+
- {{domxref("FetchLaterResult")}}
55+
- : Represents the result of requesting a deferred fetch.
56+
57+
## HTTP headers
58+
59+
- {{HTTPHeader("Permissions-Policy/deferred-fetch", "deferred-fetch")}}
60+
- : Controls [top-level quota](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for the `fetchLater()` API.
61+
- {{HTTPHeader("Permissions-Policy/deferred-fetch-minimal", "deferred-fetch-minimal")}}
62+
- : Controls [shared cross-origin subframe quota](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas) for the `fetchLater()` API.
63+
64+
## Specifications
65+
66+
{{Specifications}}
67+
68+
## Browser compatibility
69+
70+
{{Compat}}
71+
72+
## See also
73+
74+
- [`fetchLater()` quotas](/en-US/docs/Web/API/fetchLater_API/fetchLater_quotas)
75+
- [Fetch API](/en-US/docs/Web/API/Fetch_API)

0 commit comments

Comments
 (0)