Skip to content

Commit

Permalink
zh-cn: resolve the global function fetch()
Browse files Browse the repository at this point in the history
  • Loading branch information
yin1999 committed Jul 17, 2024
1 parent d8531f0 commit 0df43d9
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 118 deletions.
297 changes: 180 additions & 117 deletions files/zh-cn/web/api/window/fetch/index.md
Original file line number Diff line number Diff line change
@@ -1,179 +1,241 @@
---
title: 全局函数 fetch()
title: Window:fetch() 方法
slug: Web/API/Window/fetch
original_slug: Web/API/fetch
l10n:
sourceCommit: 272cd2b471705d5071dd63764ba13b4c46a260d7
sourceCommit: 80d3325431bf238f06c986c2dc78944ac5227372
---

{{APIRef("Fetch API")}}{{AvailableInWorkers}}
{{APIRef("Fetch API")}}

全局 **`fetch()`** 方法用于发起获取资源的请求,它会返回一个会在请求响应后兑现的 promise。
{{domxref("Window")}} 接口的 **`fetch()`** 方法用于发起获取资源的请求,它会返回一个会在请求响应后兑现的 promise。

该 promise 会兑现一个表示请求响应的 {{domxref("Response")}} 对象。

当遇到网络错误(因为权限或其他类似的问题)时,`fetch()` 返回的 promise 才会被拒绝。`fetch()` 的 promise *不会*因为 HTTP 错误而被拒绝(比如 `404``504`,等)。因此,`then()` 处理器必须检查 {{domxref("Response.ok")}} 和/或 {{domxref("Response.status")}} 属性。
当请求失败(例如,因为请求 URL 的格式错误或网络错误)时,`fetch()` promise 才会被拒绝。`fetch()` 的 promise *不会*因为服务器响应表示错误的 HTTP 状态码(`404``504`,等)而被拒绝。因此,`then()` 处理器必须检查 {{domxref("Response.ok")}} 和/或 {{domxref("Response.status")}} 属性。

`fetch()` 方法由 [Content Security Policy](/zh-CN/docs/Security/CSP/CSP_policy_directives) `connect-src` 指令控制,而不是它请求的资源
`fetch()` 方法由[内容安全策略](/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy)`connect-src` 指令(而不是它查询的资源的指令)控制

> **备注:** `fetch()` 方法的参数与 {{domxref("Request.Request","Request()")}} 构造器是一样的
> **备注:** `fetch()` 方法的参数与 {{domxref("Request.Request","Request()")}} 构造函数是一样的
## 语法

```plain
Promise<Response> fetch(input[, init]);
```js-nolint
fetch(resource)
fetch(resource, options)
```

### 参数

- `resource`

- : 定义你想要获取的资源。这可能是
- : 定义你想要获取的资源。可以是

- 一个字符串或任何其他具有 {{Glossary("stringifier")}} 的对象包括 {{domxref("URL")}} 对象——提供你想要获取的资源的 URL。
- 一个字符串或任何其他具有{{Glossary("stringifier", "字符串化器")}}的对象包括 {{domxref("URL")}} 对象),提供你想要获取的资源的 URL。URL 可以是相对于基础 URL 的,基础 URL 是窗口上下文中文档的 {{domxref("Node.baseURI", "baseURI")}} 或者 worker 上下文中的 {{domxref("WorkerGlobalScope.location")}}
- 一个 {{domxref("Request")}} 对象。

- `options` {{optional_inline}}

- : 一个包含要应用于请求的自定义设置的对象。可能的选项有:

- `body`

- : 你想要添加到请求中的任意消息主体:可以是一个 {{domxref("Blob")}}、{{jsxref("ArrayBuffer")}}、{{jsxref("TypedArray")}}、{{jsxref("DataView")}}、{{domxref("FormData")}}、{{domxref("URLSearchParams")}}、字符串对象或者字符串字面量,或者 {{domxref("ReadableStream")}} 对象。注意 `GET``HEAD` 方法的请求不能包含消息主体。

- `browsingTopics` {{experimental_inline}}

- : 布尔值,表示当前用户选择的主题是否应该在关联请求的 {{httpheader("Sec-Browsing-Topics")}} 标头中发送。有关更多详细信息,请参阅[使用 Topics API](/zh-CN/docs/Web/API/Topics_API/Using)

- `cache`

- : 字符串,表示请求如何与浏览器的 [HTTP 缓存](/zh-CN/docs/Web/HTTP/Caching)进行交互。可能的值有 `default``no-store``reload``no-cache``force-cache``only-if-cached`,这些取值在 {{domxref("Request")}} 对象的 {{domxref("Request/cache", "cache")}} 属性的文档中有记录。

- `credentials`

- : 控制浏览器如何处理凭据([cookie](/zh-CN/docs/Web/HTTP/Cookies)[HTTP authentication](/zh-CN/docs/Web/HTTP/Authentication) 条目和 TLS 客户端证书)。必须是以下字符串之一:

- `omit`:告诉浏览器在请求中排除凭据,并忽略响应中发送的任何凭据(例如,任何 {{HTTPHeader("Set-Cookie")}} 标头)。
- `same-origin`:告诉浏览器在请求同源 URL 时包含凭据,并使用来自同源 URL 响应中返回的凭据。**这是默认值。**
- `include`:告诉浏览器在同源和跨源请求中都包含凭据,并始终使用响应中返回的凭据。

> **备注:** 凭据可以包含在简单和“最终”的跨源请求中,但不应包含在 [CORS 预检请求](/zh-CN/docs/Web/HTTP/CORS#预检请求)中。
- `headers`

- : 任意你想要附加到请求的标头,可以是 {{domxref("Headers")}} 对象或者带有{{jsxref("String", "字符串")}}值的对象字面量。注意[有些标头是被禁止的](/zh-CN/docs/Glossary/Forbidden_header_name)

> **备注:** 请求中可能会有 [`Authorization`](/zh-CN/docs/Web/HTTP/Headers/Authorization) HTTP 标头,但是如果请求跨源重定向的话就会被删除。
- `integrity`

- : 包含请求的[子资源完整性](/zh-CN/docs/Web/Security/Subresource_Integrity)值(比如 `sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=`)。

- `keepalive`
- : `keepalive` 选项可以允许请求持续保持连接,甚至页面已经关闭的情况。使用 `keepalive` 标志的 Fetch 是 {{domxref("Navigator.sendBeacon()")}} API 的一种替代方案。
- `method`

- : 请求的方法,比如 `"GET"``"POST"`,默认值是 `"GET"`。注意 {{HTTPMethod("HEAD")}} 或者 {{HTTPMethod("GET")}} 的 Fetch 请求不会设置 {{httpheader("Origin")}} 标头(此行为已在 Firefox 65 中修正——参见 [Firefox bug 1508661](https://bugzil.la/1508661))。不区分大小写的情况下能匹配上 [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110#name-overview) 中的任意字符串都会自动被转成大小。如果你想使用自定义的方法(比如 `PATCH`),你应该将它变为大写。

- `mode`
- : 你想要使用的模式,比如 `cors``no-cors``same-origin`
- `priority`
- : 指定相对于其他同类型的请求的 fetch 请求的优先级。必须是以下字符串之一:
- `high`
- : 相对于其他同类型的请求而言,这是一个高优先级的 fetch 请求。
- `low`
- : 相对于其他同类型的请求而言,这是一个低优先级的 fetch 请求。
- `auto`
- : 自动确定相对于同类型的其他请求的 fetch 请求的优先级(默认)。
- `redirect`

- : 如何处理重定向(`redirect`)响应:

- `follow`
- : 自动跟随重定向。除非另有说明,否则重定向模式设置为 `follow`
- `error`
- : 如果发生重定向,则中止并显示错误。
- `manual`
- : 调用者打算在另一个上下文中处理响应。详细信息请参阅 [WHATWG fetch 规范](https://fetch.spec.whatwg.org/#concept-request-redirect-mode)

- `referrer`

- : 一个指定请求的引用者的字符串。这可以是同源 URL、`about:client` 或空字符串。

- `referrerPolicy`
- : 指定请求所使用的 [referrer policy](https://w3c.github.io/webappsec-referrer-policy/#referrer-policies)。可能是以下其中之一 `no-referrer``no-referrer-when-downgrade``same-origin``origin``strict-origin``origin-when-cross-origin``strict-origin-when-cross-origin` 或者 `unsafe-url`
- `signal`
- : 一个 {{domxref("AbortSignal")}} 对象实例;允许你通过 {{domxref("AbortController")}} 与 fetch 请求进行通信,并在需要时中止请求。
- : 一个包含你想要应用到请求上的任何自定义设置的 {{domxref("RequestInit")}} 对象。

### 返回值

一个 {{jsxref("Promise")}},resolve 时回传 {{domxref("Response")}} 对象。

### 例外

| 类型 | **描述** |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `AbortError` | 请求被{{domxref("AbortController.abort()")}}终止。 |
| `TypeError` |[Firefox 43](/zh-CN/docs/Mozilla/Firefox/Releases/43)开始,如果`fetch()`接收到含有用户名和密码的 URL(例如`http://user:[email protected]`),它将会抛出一个`TypeError`|
一个 {{jsxref("Promise")}},会兑现 {{domxref("Response")}} 对象。

### 异常

- `AbortError` {{domxref("DOMException")}}
- : 请求被 {{domxref("AbortController")}} 的 {{domxref("AbortController.abort", "abort()")}} 方法调用所终止。
- `NotAllowedError` {{domxref("DOMException")}}
- : 如果 [Topics API](/zh-CN/docs/Web/API/Topics_API) 的使用被 {{httpheader('Permissions-Policy/browsing-topics','browsing-topics')}} [权限策略](/zh-CN/docs/Web/HTTP/Permissions_Policy)明确禁止,且 `fetch()` 请求中包含 `browsingTopics: true`,则会抛出此异常。
- {{jsxref("TypeError")}}
- : 可以由以下原因引起:

<table>
<thead>
<tr>
<th scope="col">原因</th>
<th scope="col">失败的示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>被权限策略阻止</td>
<td><a href="/zh-CN/docs/Web/API/Attribution_Reporting_API">Attribution Reporting API</a> 的使用被 <a href="/zh-CN/docs/Web/HTTP/Headers/Permissions-Policy/attribution-reporting"><code>attribution-reporting</code></a> {{httpheader("Permissions-Policy")}} 所阻止,而 <code>fetch()</code> 请求又指定了 <code>attributionReporting</code>。</td>
</tr>
<tr>
<td>无效的标头名称。</td>
<td>
<pre>
// “C ontent-Type”中的空格
const headers = {
'C ontent-Type': 'text/xml',
'Breaking-Bad': '<3',
};
fetch('https://example.com/', { headers });
</pre>
</td>
</tr>
<tr>
<td>
无效的标头值。标头对象必须明确包含两个元素。
</td>
<td>
<pre>
const headers = [
['Content-Type', 'text/html', 'extra'],
['Accept'],
];
fetch('https://example.com/', { headers });
</pre>
</td>
</tr>
<tr>
<td>
无效的 URL 或方案(scheme),或使用 fetch 不支持的方案,或使用不支持特定请求模式的方案。
</td>
<td>
<pre>
fetch('blob://example.com/', { mode: 'cors' });
</pre>
</td>
</tr>
<td>URL 中包含凭据。</td>
<td>
<pre>
fetch('https://user:[email protected]/');
</pre>
</td>
<tr>
<td>无效的来源(referrer)URL。</td>
<td>
<pre>
fetch('https://example.com/', { referrer: './abc\u0000df' });
</pre>
</td>
</tr>
<tr>
<td>无效的模式(<code>navigate</code> 和 <code>websocket</code>)。</td>
<td>
<pre>
fetch('https://example.com/', { mode: 'navigate' });
</pre>
</td>
</tr>
<tr>
<td>
如果请求的缓存模式是“only-if-cached”,而请求模式不是“same-origin”。
</td>
<td>
<pre>
fetch('https://example.com/', {
cache: 'only-if-cached',
mode: 'no-cors',
});
</pre>
</td>
</tr>
<tr>
<td>
如果请求方法是无效的名称标记或被禁止的标头之一(<code>'CONNECT'</code>、<code>'TRACE'</code> 或 <code>'TRACK'</code>)。
</td>
<td>
<pre>
fetch('https://example.com/', { method: 'CONNECT' });
</pre>
</td>
</tr>
<tr>
<td>
如果请求的模式是“no-cors”,而请求方法不是列入 CORS 白名单的方法(<code>'GET'</code>、<code>'HEAD'</code> 或 <code>'POST'</code>)。
</td>
<td>
<pre>
fetch('https://example.com/', {
method: 'CONNECT',
mode: 'no-cors',
});
</pre>
</td>
</tr>
<tr>
<td>
如果请求方法是 <code>'GET'</code> 或 <code>'HEAD'</code>,而请求体不是 <code>null</code> 或 <code>undefined</code>。
</td>
<td>
<pre>
fetch('https://example.com/', {
method: 'GET',
body: new FormData(),
});
</pre>
</td>
</tr>
<tr>
<td>如果 fetch 抛出了网络错误。</td>
<td></td>
</tr>
</tbody>
</table>

## 示例

[Fetch Request 示例](https://github.com/mdn/fetch-examples/tree/gh-pages/fetch-request) (参见 [Fetch Request live](http://mdn.github.io/fetch-examples/fetch-request/)) 中,我们使用对应的构造器创建了一个新的 {{domxref("Request")}} 对象,然后调用 fetch() 方法获取资源。因为我们是在请求一个图片,为了解析正常,我们对响应执行 {{domxref("Body.blob")}} 来设置相应的 MIME 类型。然后创建一个 Object URL,并在 {{htmlelement("img")}} 元素中把它显示出来。
[Fetch 请求示例](https://github.com/mdn/fetch-examples/tree/gh-pages/fetch-request)(查看 [Fetch 请求在线示例](http://mdn.github.io/fetch-examples/fetch-request/))中,我们使用对应的构造函数创建了一个新的 {{domxref("Request")}} 对象,然后调用 `fetch()` 获取资源。因为我们是在请求一个图片,为了解析正常,我们对响应执行 {{domxref("Body.blob")}} 来设置相应的 MIME 类型。然后创建一个 Object URL,并在 {{htmlelement("img")}} 元素中把它显示出来。

```js
var myImage = document.querySelector("img");
const myImage = document.querySelector("img");

var myRequest = new Request("flowers.jpg");
const myRequest = new Request("flowers.jpg");

window
.fetch(myRequest)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP 错误!状态:${response.status}`);
}

fetch(myRequest)
.then(function (response) {
return response.blob();
})
.then(function (response) {
var objectURL = URL.createObjectURL(response);
myImage.src = objectURL;
.then((response) => {
myImage.src = URL.createObjectURL(response);
});
```

[Fetch with init then Request 示例](https://github.com/mdn/fetch-examples/tree/gh-pages/fetch-with-init-then-request) (参见 [Fetch Request init live](http://mdn.github.io/fetch-examples/fetch-with-init-then-request/)) 中,我们做同样的操作,除了在调用 fetch() 时传入一个 init 对象:
[带有初始化的 Fetch 请求示例](https://github.com/mdn/fetch-examples/tree/gh-pages/fetch-with-init-then-request)(查看[带有初始化的 Fetch 请求在线示例](http://mdn.github.io/fetch-examples/fetch-with-init-then-request/)中,我们做同样的操作,除了在调用 `fetch()` 时传入了 _options_ 对象。在本例中,我们可以设置 {{HTTPHeader("Cache-Control")}} 值来指示我们可以接受什么类型的缓存响应

```js
var myImage = document.querySelector('img');
const myImage = document.querySelector("img");
const reqHeaders = new Headers();

var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
// 除非缓存的响应超过一周,否则都可以接受
reqHeaders.set("Cache-Control", "max-age=604800");

var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
const options = {
headers: reqHeaders,
};

var myRequest = new Request('flowers.jpg');
// 将带有标头的“options”对象作为 init 来传递。
const req = new Request("flowers.jpg", options);

fetch(myRequest,myInit).then(function(response) {
...
fetch(req).then((response) => {
// ...
});
```

你也可以传入同样的 init 对象到 Request 构造器,来实现同样的效果,如
你也可以传入同样的 `init` 对象到 `Request` 构造函数,来实现同样的效果:

```js
var myRequest = new Request("flowers.jpg", myInit);
const req = new Request("flowers.jpg", options);
```

`init` 对象中的 `headers` 也可以是一个对象字面量:

```js
var myInit = {
method: "GET",
const options = {
headers: {
"Content-Type": "image/jpeg",
"Cache-Control": "max-age=60480",
},
mode: "cors",
cache: "default",
};

var myRequest = new Request("flowers.jpg", myInit);
const req = new Request("flowers.jpg", options);
```

## 规范
Expand All @@ -186,6 +248,7 @@ var myRequest = new Request("flowers.jpg", myInit);

## 参见

- {{domxref("WorkerGlobalScope.fetch()")}}
- [Fetch API](/zh-CN/docs/Web/API/Fetch_API)
- [ServiceWorker API](/zh-CN/docs/Web/API/Service_Worker_API)
- [HTTP 访问控制(CORS)](/zh-CN/docs/Web/HTTP/CORS)
Expand Down
2 changes: 1 addition & 1 deletion files/zh-cn/web/api/window/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ _本接口从 {{domxref("EventTarget")}} 接口继承方法。_
- : 用于触发事件。
- {{domxref("Window.dump()")}} {{Non-standard_Inline}}
- : 向控制台中写一条消息。
- {{domxref("fetch", "Window.fetch()")}}
- {{domxref("Window.fetch()")}}
- : 开始从网络获取资源的过程。
- {{domxref("Window.find()")}} {{Non-standard_Inline}}
- : 在窗口中搜索给定的字符串。
Expand Down
Loading

0 comments on commit 0df43d9

Please sign in to comment.