Fetch方法的使用

介绍

Fetch是基于Promise开发的用于访问和操纵 HTTP 管道的一个API。其提供了一个全局 fetch()方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

以前浏览器中的网络请求只能通过XMLHttpRequest实现(虽然大多使用的是封装过后的接口)。而Fetch则结合Promise提供了一种更加简化的发送网络请求的方式(其调用方法与axiso相似)。

用法

Fetch()方法

Fetch接受两个参数:

Promise<Response> fetch(input[, init]);

  • ?input

    定义要获取的资源。这可能是:一个 USVString字符串,包含要获取资源的 URL。一些浏览器会接受 blob:data: 作为 schemes.一个 Request对象。

  • init 可选

    一个配置项对象,包括所有对请求的设置。可选的参数有:

    • method: 请求使用的方法,如 GET、POST。
    • headers: 请求的头信息,形式为 Headers值的对象字面量。
    • body: 请求的 body 信息:可能是一个 BlobBufferSourceFormDataURLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
    • mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
    • credentials: 请求的 credentials,如 omit、same-origin 或者include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例。
    • cache: 请求的 cache 模式: defaultno-storereloadno-cache force-cache 或者 only-if-cachedredirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中默认使用follow(Chrome 47之前的默认值是manual)。
    • referrer: 一个 [USVString](https://developer.mozilla.org/zh-CN/docs/Web/API/USVString) 可以是 no-referrer、``client或一个 URL。默认是 client。`
    • referrerPolicy: 指定了HTTP头部referer字段的值。可能为以下值之一: no-referrer、no-referrer-when-downgrade、origin、origin-when-cross-origin、unsafe-url
    • integrity: 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。

返回值

一个 Promise对象。

例子

发送带凭据的请求

注意:Fetch默认是不携带凭据的请求(即使是跨域源),要将credentials: 'include'添加到传递给 fetch()方法的init对象,才能使请求携带凭证。

1
2
3
fetch('https://example.com', {
credentials: 'include'
})

如果你只想在请求URL与调用脚本位于同一起源处时发送凭据,请添加 credentials: 'same-origin'

1
2
3
4
5
// The calling script is on the origin 'https://example.com'

fetch('https://example.com', {
credentials: 'same-origin'
})

上传 JSON 数据

使用 fetch() POST JSON数据

1
2
3
4
5
6
7
8
9
10
11
12
var url = 'https://example.com/profile';
var data = {username: 'example'};

fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data), // data can be `string` or {object}!
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

上传文件

可以通过 HTML <input type="file" /> 元素,FormData()fetch()上传文件。

1
2
3
4
5
6
7
8
9
10
11
12
var formData = new FormData();
var fileField = document.querySelector("input[type='file']");

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
method: 'PUT',
body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))

上传多个文件

可以通过HTML <input type="file" mutiple/> 元素,FormData()fetch()上传多个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var formData = new FormData();
var photos = document.querySelector("input[type='file'][multiple]");

formData.append('title', 'My Vegas Vacation');
// formData 只接受文件、Blob 或字符串,不能直接传递数组,所以必须循环嵌入
for (let i = 0; i < photos.files.length; i++) {
formData.append('photo', photos.files[i]);
}

fetch('https://example.com/posts', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));

自定义请求对象

除了传给 fetch() 一个资源的地址,你还可以通过使用 Request()构造函数来创建一个 request 对象,然后再作为参数传给 fetch()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var myHeaders = new Headers();

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

var myRequest = new Request('flowers.jpg', myInit);

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

Request()fetch() 接受同样的参数。你甚至可以传入一个已存在的 request 对象来创造一个拷贝:

1
var anotherRequest = new Request(myRequest,myInit);

Request对象

Request构造器可以构造一个Request对象,其作为Fetch方法的参数。

该构造器接受的参数与Fetch一致:

  1. 请求地址
  2. init对象

此处不再赘述。

此外,我们可直接通过const method = Request.method的方式来获取init属性。如:

1
2
3
4
5
const myRequest = new Request('http://localhost/flowers.jpg');

const myURL = myRequest.url; // http://localhost/flowers.jpg
const myMethod = myRequest.method; // GET
const myCred = myRequest.credentials; // omit

方法

Request对象有以下方法可以调用:

  • Request.clone()

    创建当前request的副本。

Request实现 Body`, 因此它也有以下方法可用:

  • Body.arrayBuffer()

    返回解决一个ArrayBuffer表示的请求主体的promise.

  • Body.blob()

    返回解决一个Blob表示的请求主体的promise.

  • Body.formData()

    返回解决一个FormData表示的请求主体的promise.

  • Body.json()

    返回解决一个JSON表示的请求主体的promise.

  • Body.text()

    返回解决一个USVString(文本)表示的请求主体的promise.

注意:这些Body功能只能运行一次; 随后的调用将通过空strings/ ArrayBuffers解析.

header对象

使用 Headers的接口,你可以通过 Headers()构造函数来创建一个你自己的 headers 对象。一个 headers 对象是一个简单的多名值对:

1
2
3
4
5
let content = "Hello World";
let myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

也可以直接接受一个字面量对象来构造header对象

1
2
3
4
5
myHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"X-Custom-Header": "ProcessThisImmediately",
});

方法

  • Headers.append()

    给现有的header添加一个值, 或者添加一个未存在的header并赋值.

  • Headers.delete()

    从Headers对象中删除指定header.

  • Headers.entries()

    迭代器 的形式返回Headers对象中所有的键值对.

  • Headers.get()

    ByteString 的形式从Headers对象中返回指定header的全部值.

  • Headers.has()

    以布尔值的形式从Headers对象中返回是否存在指定的header.

  • Headers.keys()

    迭代器的形式返回Headers对象中所有存在的header名.

  • Headers.set()

    替换现有的header的值, 或者添加一个未存在的header并赋值.

  • Headers.values()

    迭代器的形式返回Headers对象中所有存在的header的值.

注意

  • 在header已存在或者有多个值的状态下Headers.set()Headers.append()的使用有如下区别, Headers.set()将会用新的值覆盖已存在的值, 但是Headers.append()会将新的值添加到已存在的值的队列末尾.
  • 如果您尝试传入名称不是有效的HTTP头名称的引用,则所有Headers方法都将引发 TypeError 。 如果头部有一个不变的Guard,则变异操作将会抛出一个 TypeError 。 在其他任何失败的情况下,他们默默地失败。
  • 出于安全考虑,某些头只能由用户代理控制。这些头信息包括 forbidden header namesforbidden response header names
  • 一个Headers对象也有一个关联的guard,它具有不可变的值,requestrequest-no-corsresponsenone。 这会影响 set()delete(), 和append()`方法 改变header.

Guard属性

描述

Guard 是 Headers对象的特性,基于不同的情况,它可以有以下取值:immutable、request、request-no-cors、response 或 none。

由于 Headers 可以在 request 请求中被发送或者在 response 请求中被接收,并且规定了哪些参数是可写的,Headers 对象中的 guard 属性。这个属性没有暴露给 Web,但是它影响到哪些内容可以在 Headers 对象中被操作。

规则

当使用 Headers()constructor创建一个新的 Headers对象的时候,它的 guard 被设置成 none(默认值)。当创建 RequestResponse对象的时候,它将拥有一个按照以下规则实现的与之关联的 Headers`对象:

新对象的类型 创建时的构造函数 关联的 Headers对象的 guard
Request Request() request
Request Request(),mode 设置成 no-cors request-no-cors
Response Response() response
Response immutable immutable

guard属性值的特征:

  • none:默认的
  • request:从 request 中获得的 headers(Request.headers)只读
  • request-no-cors:从不同域(Request.mode no-cors)的 request 中获得的 headers 只读
  • response:从 response 中获得的 headers(Response.headers)只读
  • immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读。

Response 对象

描述

如上所述,Response实例是在 fetch() 处理完 promise 之后返回的。其呈现了对一次请求的响应数据。

我们可以通过一个构造函数来创建一个Response对象,但更多的是通过一个Fetch请求返回的Response对象。

属性

  • Response.headers只读

    包含此 Response 所关联的 Headers对象。

  • Response.ok只读

    包含了一个布尔值,标示该 Response 成功(HTTP 状态码的范围在 200-299)。

  • Response.redirected只读

    表示该 Response 是否来自一个重定向,如果是的话,它的 URL 列表将会有多个条目。

  • Response.status只读

    包含 Response 的状态码 (例如 200 表示成功)。

  • Response.statusText只读

    包含了与该 Response 状态码一致的状态信息(例如,OK对应 200)。

  • Response.type 只读

    包含 Response 的类型(例如,basiccors)。

  • Response.url只读

    包含 Response 的URL。

  • Response.useFinalURL

    包含了一个布尔值,来标示这是否是该 Response 的最终 URL。

Response 实现了 Body接口,所以以下属性亦可用:

  • Body.body 只读

    一个简单的 getter,用于暴露一个 ReadableStream类型的 body 内容。

  • Body.bodyUsed只读

    包含了一个布尔值来标示该 Response 是否读取过 Body

方法

  • Response.clone()

    创建一个 Response 对象的克隆。

  • Response.error()

    返回一个绑定了网络错误的新的 Response 对象。

  • Response.redirect()

    用另一个 URL 创建一个新的 Response

Response 实现了 Body接口,所以以下方法同样可用:

  • Body.arrayBuffer()

    读取 Response对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 ArrayBuffer格式的 Promise 对象。

  • Body.blob()

    读取 Response对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 Blob 格式的 Promise 对象。

  • Body.formData()

    读取Response对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 FormData 格式的 Promise 对象。

  • Body.json()

    读取 Response对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 JSON 格式的 Promise 对象。

  • Body.text()

    读取 Response对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 USVString 格式的 Promise 对象。

body对象

**Body**代表响应/请求的正文,允许你声明其内容类型是什么以及应该如何处理。

一般我们也是从一个请求中得到一个body对象。当然,直接通过body构造器来创建一个body也是被允许的。

属性

  • Body.body 只读
    一个简单的getter用于暴露一个ReadableStream类型的主体内容。
  • Body.bodyUsed 只读
    一个Boolean 值指示是否body已经被标记读取。

方法

  • Body.arrayBuffer()

    使Response挂起一个流操作并且在完成时读取其值,它返回一个Promise对象,其resolve参数类型是ArrayBuffer。此操作会将bodyUsed状态改为已使用(true)。

  • Body.blob()

    使Response挂起一个流操作并且在完成时读取其值,它返回一个Promise对象,其resolve参数类型是Blob。此操作会将bodyUsed状态改为已使用(true)。

  • Body.formData()

    使Response挂起一个流操作并且在完成时读取其值,它返回一个Promise对象,其resolve参数类型是FormData表单。此操作会将bodyUsed状态改为已使用(true)。

  • Body.json()

    使Response挂起一个流操作并且在完成时读取其值,它返回一个Promise对象,其resolve参数类型是使用JSON解析body文本的结果。此操作会将bodyUsed状态改为已使用(true)。

  • Body.text()

    使Response挂起一个流操作并且在完成时读取其值,它返回一个Promise对象,其resolve参数类型是USVString(文本)。此操作会将bodyUsed状态改为已使用(true)。

比起XHR来,这些方法让非文本化的数据使用起来更加简单。

兼容性

可以看到Fetch的兼容性还是有一定的问题,Chrome42版本才开始支持从与Firefox从39版本才支持,而IE到目前位置都不支持。这是一个很大的问题。如果要在生产环境中使用,必须引入很多pollyfill,相较于使用Promise封装的XHR,这样看来优势又荡然无存,随着版本的迭代,未来肯定是Fetch的,但不是现在。

参考

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :