第九章 JavaScript 异步编程专题 9. 5 Fetch API

9.5 Fetch API

Fetch 是一种在浏览器中发起网络请求的 API,它提供了一种更加现代化、灵活的方式来处理网络请求,相较于传统的 XMLHttpRequest,Fetch API 返回的是 Promise 对象,解决了早期使用 XHR API 时需要设置多个事件监听器的问题,使代码更加简洁易读。

fetch()

fetch() 方法的基本语法如下:
fetch(resource[, options])
其中,resource 表示请求的 URL 地址或 Request 对象;options 是一个可选的对象,用于指定请求的参数。
fetch() 方法的参数说明如下:
resource:表示请求的 URL 地址或 Request 对象,可以是绝对路径或相对路径。如果是相对路径,将相对于当前页面的地址解析。
options:表示请求的参数,包括 method、headers、body、mode、credentials、cache、redirect、referrer、integrity、keepalive 等。该参数是一个对象,可以省略。
举个例子,使用 fetch() 方法发送一个 GET 请求:

fetch('https://example.com/api/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

使用 fetch() 方法发送一个 POST 请求:

const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      username: 'john',
      password: '123456'
    })
  };
  
  fetch('https://example.com/api/login', options)
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

下面继续详细讲解参数options对象的属性:

options.method

请求使用的方法,如 GET、POST、PUT、DELETE 等。默认为 GET。

options.headers

请求头对象,可以设置自定义的请求头信息。在 headers 属性中,每个键值对表示一个 HTTP 请求头,键名表示请求头的名称,键值表示请求头的值。值得注意的是,headers 属性不会覆盖默认的请求头,而是会和默认请求头合并。
默认的请求头包括以下内容:
1 Accept:指定客户端可以接受的内容类型。
2 Accept-Charset:指定客户端可以接受的字符集。
3 Accept-Encoding:指定客户端可以接受的内容编码方式。
4 Accept-Language:指定客户端可以接受的自然语言。
5 User-Agent:指定客户端使用的浏览器和操作系统等信息。
这些请求头不会被覆盖,因为 Fetch API 默认会设置这些请求头。如果需要完全覆盖默认的请求头,可以使用 Request 对象,自定义所有的请求头。例如:

const myHeaders = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
});

const options = {
  method: 'POST',
  headers: myHeaders,
  body: JSON.stringify({
    username: 'john',
    password: '123456'
  })
};

options.body

fetch的body 就是设置http请求的body,可以是JSON字符串、FormData 对象、Blob 或 ArrayBuffer 等类型。注意在类型是FormData和Blob时,Content-Type会自动设置合适的值,而类型是JSON字符串和ArrayBuffer时需要手动设置。注意 GET 或 HEAD 方法的请求不能包含 body 信息。看下边的例子:

// 使用 FormData 作为请求体,Content-Type 会被自动设置为 multipart/form-data

const formData = new FormData();
formData.append('username', 'john.doe');
formData.append('password', '123456');

fetch(url, {
  method: 'POST',
  body: formData
})
.then(response => console.log(response))
.catch(error => console.error(error));

// 使用 Blob 作为请求体,Content-Type 会被自动设置为该 Blob 对象的 type 属性的值
const blob = new Blob(['Hello, world!'], { type: 'text/plain' });

fetch(url, {
  method: 'POST',
  body: blob
})
.then(response => console.log(response))
.catch(error => console.error(error));

// 使用 ArrayBuffer 作为请求体,需要手动设置 Content-Type
const buffer = new ArrayBuffer(8);

fetch(url, {
  method: 'POST',
  body: buffer,
  headers: {
    'Content-Type': 'application/octet-stream'
  }
})
.then(response => console.log(response))
.catch(error => console.error(error));
const data = { username: 'example' };
// 使用 JSON 字符串 作为请求体,需要手动设置 Content-Type
fetch('https://example.com/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

options.referrerPolicy

用于控制浏览器将哪些信息包含在请求头中的 Referer 字段中。可选值如下:
1 no-referrer: 请求头不包含 Referer 字段。
2 no-referrer-when-downgrade: 默认值,当站点从https协议发送请求到http协议时,不会发送Referer 字段。
3 same-origin: “same-origin” 选项指示在同一源内进行请求时将完整的 Referer 信息发送给服务器,但在跨源请求时不发送 Referer 信息。如果您希望在同一源内发送 Referer 并在跨源请求中不发送,则可以使用此选项。
4 origin: 例如,如果请求的 URL 是 example.com/path,那么使用 “origin” 模式发送的 Referer 就是 example.com,包括了协议和端口号。
5 strict-origin: 只发送请求页面的源信息,而不包含路径、查询参数等其他信息。如果请求是从 HTTPS 页面到 HTTP 页面的,那么就不会发送 Referrer。例如,如果请求页面是 example.com/page1,那么 Referrer 会设置为 example.com/。但是如果是从 example.com/page1example.net/page2,则不会发送 Referrer。
6 origin-when-cross-origin: 如果请求从同一站点发出,则请求头包含完整的路径信息和查询字符串;如果不是,则请求头只包含源。
7 strict-origin-when-cross-origin: 如果请求从同一站点发出,则请求头包含完整的路径信息和查询字符串;如果不是,则请求头不包含 Referer 字段。
8 unsafe-url:在 Referer 中始终发送完整的 url,即使当站点从https协议发送请求到http协议和跨域时。
referrerPolicy 参数用于控制浏览器将哪些信息包含在请求头中的 Referer 字段中,保护用户的隐私安全,避免泄露敏感信息。正常情况下不需要该参数。

options.referrer

referrer选项可以用来设置任何当前域内的Referer,或者移除Referer。它可以设置为以下任意一项:
1 no-referrer: 不发送Referer。
2 client: 默认值,发送完整的Referer。
3 ”(空字符串): 发送完整的Referer
referrer字段大多数情况下我们都不需要关心,它的内容与接口和当前页面是否同源,是有从https请求http有关,所以当有这方面需求的时候还请实际去测试每一个参数值的具体作用,找到符合需求的方式。

options.mode

用来指定请求的模式。该参数有以下几个可选值:
1 cors:默认值,跨域请求,需要服务器端设置响应头 Access-Control-Allow-Origin 允许跨域访问才能成功。
2 same-origin:同源请求,只有在当前页面的协议、域名、端口都相同时才会被允许。
3 no-cors:在使用 Fetch API 发送跨域请求时,浏览器会根据同源策略(Same-Origin Policy)进行限制。但是,同源策略并不会完全禁止跨域请求,只是限制了对响应的访问权限。具体来说,如果发送跨域请求,响应中的一些数据(例如响应头、状态码等)可能无法访问。
为了解决这个问题,Fetch API 提供了 no-cors 模式。当设置为 no-cors 模式时,浏览器会发送一个简单的跨域请求,并且不会带上额外的头信息。这意味着在 no-cors 模式下,我们无法读取响应的数据,例如响应头、状态码和响应正文等。需要注意的是,当使用 no-cors 模式时,请求的方法只能是 GET、HEAD 或 POST,并且请求的 body 只能是 Blob 或 FormData 类型。同时,服务器必须设置允许跨域请求,并且响应头不能包含 Set-Cookie、Vary 或 Content-Encoding 等字段。

options.credentials

credentials 用于指定是否在请求中发送cookie信息。
credentials 属性有三个值:
1 omit:不在请求中发送凭据信息。
2 same-origin:只在同源请求中发送凭据信息(默认值)。
3 include:在跨域请求中也发送凭据信息。如果我们要向跨域的 API 发送带有 cookie 的请求,还需要将 credentials 属性设置为 “include”, 同时服务端也要返回header Access-Control-Allow-Credentials: true。
options.cache
cache 的可选值有以下几种:
1 “default”(默认值):浏览器按照常规的缓存机制来处理请求和响应;
2 “no-store”:禁用缓存机制,每次请求都会从网络加载数据;
3 “reload”:忽略缓存,强制从网络加载数据;
4 “no-cache”:不使用浏览器缓存,但是使用已存在的缓存;
5 “force-cache”:强制使用浏览器缓存;
6 “only-if-cached”:只使用浏览器缓存,如果缓存中没有数据则请求失败。
需要注意的是,缓存机制的实现并不是由 Fetch API 来控制的,而是由浏览器来控制的。因此,具体的缓存行为可能因浏览器的实现而有所不同。
几个容易混淆的值:
no-store: 完全不使用缓存。每次请求都会从服务器重新获取资源,即使之前的资源副本已经存在于客户端的缓存中也不会使用。
no-cache: 可以使用缓存,但必须经过协商缓存来验证它是否是最新的。服务器会返回一个验证令牌(ETag),客户端每次需要资源时都会将该令牌带上,如果该资源未被修改,则服务器返回304状态码,并告知客户端直接从缓存中读取资源,否则返回最新的资源。这种模式下,客户端可以使用之前的资源,但也会与服务器确认它是否已经过期。
reload: 忽略缓存并始终从服务器重新获取资源。
需要注意的是,cache 属性只对 GET 和 HEAD 请求有效。对于 POST 等其他类型的请求,cache 属性会被忽略。

options.redirect

redirect 是用于控制 fetch 请求的重定向行为的选项,它可以设置为以下几个值之一:
1 “follow”:默认值,自动跟随重定向,当遇到 HTTP 3xx 状态码时自动进行重定向。
2 “error”:在遇到重定向时抛出一个错误。
3 “manual”:手动处理重定向,Response 对象的 redirected 属性为 true,并且需要通过 Response 对象的 headers 属性来获取重定向后的地址。
如果您不想跟随重定向,则可以将 redirect 选项设置为 “manual” 或 “error”,然后在处理 Response 对象时,通过判断 redirected 属性来判断是否需要进行重定向,进而手动处理重定向。
Fetch API 中的 integrity 属性用于提供子资源完整性校验,可以用于验证下载的资源是否被篡改过。

options.integrity

integrity 属性表示需要验证资源完整性, integrity 属性的值是一个字符串,表示预期的完整性校验结果。字符串格式如下:algorithm-encoding-hash
其中,algorithm 是指定的哈希算法名称,如 sha256、sha384、sha512 等;encoding 是指定的哈希编码方式,如 base64、hex 等;hash 是指使用指定哈希算法计算出来的哈希值。
例如,下面的字符串表示使用 SHA-384 算法,采用 base64 编码方式,计算出来的哈希值为 U6KGPmRvBh6EBqwyz6ttkbz6IzRozb5GhejzCg9OIXB+O8IvqyWTto5KwWLQoovt:
则 integrity为
sha384-U6KGPmRvBh6EBqwyz6ttkbz6IzRozb5GhejzCg9OIXB+O8IvqyWTto5KwWLQoovt
当资源下载完成后,浏览器会对资源进行完整性校验,如果校验结果与指定的 integrity 值不一致,则会认为资源被篡改过,拒绝使用该资源。

options.keepalive

keepalive 选项表示该请求可能会在网页关闭后继续存在。通常,当页面被卸载的时候,会中断页面上的所有网络请求,但是keepalive选项告诉浏览器,该请求需要在后台继续运行。典型的场景就是在页面离开的时候发送统计数据。例如:

window.onunload = function() {
  fetch('/analytics', {
    method: 'POST',
    body: "statistics",
    keepalive: true
  });
};

注意第一 keepalive 请求的 body 限制为 64KB,第二请求成功后不能继续执行后续的代码。

signal中断Fetch请求

signal属性是一个AbortSignal实例,Fetch请求没有像XMLHttpRequest一样有abort方法可以中断请求,但是可以使用 AbortController 和 AbortSignal 中断 Fetch 请求。AbortController 是一个 API,它允许你创建一个用于中断 Fetch 请求的对象。Fetch 请求会将这个对象传递给 AbortSignal,从而使你可以在需要时中断请求。以下是中断 Fetch 请求的步骤:

  1. 创建 AbortController 对象:
    controller = new AbortController();
  2. 从 AbortController 中获取 AbortSignal 对象:
    const signal = controller.signal;
    3.将 AbortSignal 传递给 Fetch 请求
fetch(url, { signal })
  .then(response => {
    // 处理响应
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      // 请求被中断
    } else {
      // 处理其他错误
    }
  });

4.在需要中断请求的地方调用 AbortController 的 abort() 方法:
controller.abort();
这样,Fetch 请求就会在中断时触发 catch() 方法,并抛出 AbortError 异常。

Response对象

fetch方法的成功返回是一个Response类型的对象,这个对象包含了 HTTP 响应的各种信息,例如状态码、响应头、响应正文等等。开发者可以通过这个对象来获取和操作响应的内容。下面我们就看一下Response对象上的属性和方法。
response.ok
一个只读属性,返回一个布尔值,表示响应是否成功。成功的状态码为 200-299,此时是true, 这个属性在 HTTP 请求状态不是 2xx 的情况下为 false。
response.status
只读属性,返回一个整数,表示响应的状态码(例如 200 代表成功,404 代表未找到,等等)。
response.statusText
只读属性,返回一个字符串,表示响应状态的解释文本。
常见的status和statusText如下:
1 200 OK
2 201 Created
3 202 Accepted
4 204 No Content
5 300 Multiple Choices
6 301 Moved Permanently
7 302 Found
8 304 Not Modified
9 307 Temporary Redirect
10 308 Permanent Redirect
11 400 Bad Request
12 401 Unauthorized
13 403 Forbidden
14 404 Not Found
15 405 Method Not Allowed
16 406 Not Acceptable
17 408 Request Timeout
18 500 Internal Server Error
19 501 Not Implemented
20 502 Bad Gateway
21 503 Service Unavailable
22 504 Gateway Timeout
response.type
只读属性,返回一个字符串,表示响应类型(例如 “basic”、”cors”、”error”、”opaque” 或 “opaqueredirect”)。
response.url
只读属性,返回一个字符串,表示响应的 URL。
response.headers
只读属性,返回一个 Headers 对象,表示响应头的集合。后边会详细讲解Headers对象的类型。
response.redirected
只读属性,返回一个布尔值,表示响应是否被重定向。
response.body
只读属性,返回一个 ReadableStream 对象,表示响应的主体部分。Response对象提供了一些方法让用户可以非常方便的获取到body的内容。
以下是一些例子,演示如何使用 Response 对象的不同方法来处理返回的数据:
1 使用 text() 方法将响应体解析为文本数据:

fetch('/api/data')
.then(response => response.text())
.then(data => console.log(data));

2 使用 json() 方法将响应体解析为 JSON 数据:

fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));

3 使用 blob() 方法将响应体解析为 Blob 对象:

fetch('/api/image')
.then(response => response.blob())
.then(blob => {
  const url = URL.createObjectURL(blob);
  const img = document.createElement('img');
  img.src = url;
  document.body.appendChild(img);
});

4 使用 formData() 方法将响应体解析为 FormData 对象:

fetch('/api/form-data')
.then(response => response.formData())
.then(formData => {
  const entries = formData.entries();
  for (const [name, value] of entries) {
    console.log(name, value);
  }
});

5 使用 arrayBuffer() 方法将响应体解析为 ArrayBuffer 对象:

fetch('/api/binary-data')
.then(response => response.arrayBuffer())
.then(buffer => console.log(new Uint8Array(buffer)));

这些方法都返回 Promise 对象,因此可以使用 .then() 方法来处理解析后的数据。
response.body是一个 ReadableStream 对象,表示响应的主体部分,这个流对象只能被消耗一次,一旦使用了 text()、json()、blob()、formData() 或 arrayBuffer() 中的任何一个方法,就会消耗掉 Response 中的数据流,后续再次调用这些方法都将返回空值。
Response提供了clone()方法复制一份完全一样的 Response 对象,包括所有的头部信息和 body 内容,但是两个 Response 对象之间是互相独立的,互不干扰。注意,如果原始 Response 对象中的数据流已经被消耗完毕,那么克隆出来的 Response 对象也不会包含数据流。
下面是一个使用 clone() 方法的例子:

fetch('https://example.com/data')
  .then(response => {
    const responseClone = response.clone();
    return Promise.all([response.text(), responseClone.json()]);
  })
  .then(([textData, jsonData]) => {
    console.log(textData);
    console.log(jsonData);
  })
  .catch(error => {
    console.error(error);
  });

在这个例子中,我们首先使用 fetch() 方法请求一个 URL,并返回一个 Response 对象。然后,我们使用 clone() 方法创建一个 responseClone,然后同时对它进行 text() 和 json() 操作,并使用 Promise.all() 将它们组合到一起。最后,我们在 .then() 回调函数中分别输出 textData 和 jsonData。注意,由于我们使用了 clone() 方法,所以两个操作之间并不会互相干扰,它们的结果都是正确的。

ReadableStream 对象

Response对象的body属性是一个 ReadableStream 对象, ReadableStream 对象是浏览器提供的一种流式数据处理机制,可以处理大量数据而不必一次性将它们全部加载到内存中。ReadableStream 可以从网络请求、本地文件或其他来源获取数据,并将数据分成一系列的块或缓冲区,然后逐个将这些块或缓冲区推送给应用程序进行处理。
ReadableStream 对象具有以下主要特点:
1 分块读取数据:ReadableStream 将数据分成一系列的块或缓冲区,然后逐个将这些块或缓冲区推送给应用程序进行处理。这种流式处理机制可以避免一次性将所有数据加载到内存中,从而提高应用程序的性能和响应速度。
2 异步读取数据:ReadableStream 的数据读取是异步的,因此应用程序可以在读取数据时执行其他任务。
3 可中止性:ReadableStream 可以通过 cancel() 方法中止数据流的读取,从而提高应用程序的可靠性和鲁棒性。
4 支持流控制:ReadableStream 支持流控制机制,可以根据应用程序的读取速度和处理能力动态调整数据读取的速度和流量。
您可以使用浏览器提供的 fetch() 函数获取 Response 对象,然后使用 response.body 属性获取 ReadableStream 对象。然后,您可以使用 ReadableStreamDefaultReader 对象读取 ReadableStream 的数据。
以下是一个简单的示例代码:

  fetch('https://example.com/data')
  .then(response => {
    const reader = response.body.getReader();

    function readStream() {
      reader.read().then(({ done, value }) => {
        if (done) {
          console.log('Stream finished');
          return;
        }
        console.log('Received data:', value);
        readStream();
      });
    }

    readStream();
  });

在上面的示例中,我们使用 fetch() 函数获取一个数据流,然后使用 response.body.getReader() 方法创建一个 ReadableStreamDefaultReader 对象。接下来,我们定义了一个 readStream() 函数,它使用 reader.read() 方法读取 ReadableStream 的数据。当 done 属性为 true 时,表示数据已经全部读取完毕。否则,我们将处理读取到的数据,并递归调用 readStream() 函数继续读取数据。

Headers

Fetch API 中的 Headers 是一个类,用于处理 HTTP 头部信息。它提供了一系列方法来操作和读取头部信息。Headers 对象的实例可以用于 Request 和 Response 的构造函数中。有些头信息是不能手动设置或修改的属性, 这些属性是由浏览器控制的,通常与安全相关, 以保证安全性和数据隐私。在 Fetch API 中,这些头信息分别被称为 forbidden header names 和 forbidden response header names。

构造Headers对象
1 构造一个空的 Headers 对象:
const headers = new Headers();
2 构造一个包含指定头部的 Headers 对象:

const headers = new Headers({
  'Content-Type': 'application/json',
  'Accept': 'application/json'
});

3 从字符串解析头部并构造一个 Headers 对象:

const headersString = 'Content-Type: application/json\r\nAccept: application/json\r\n';
const headers = new Headers(headersString);

4 从对象转换为 Headers 对象:

const headersObject = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
};
const headers = new Headers(headersObject);

Headers.prototype.append()

Headers.prototype.append() 是 Fetch API 中 Headers 对象的一个方法,用于向头部添加一个新的键值对,如果头部中已经存在相同的键,则将值追加到现有的值列表中。
该方法的语法如下:
headers.append(name, value);
其中,name 为要添加的头部字段名,value 为要添加的头部字段值。
举个例子,我们可以使用 Headers.append() 方法向 Headers 对象添加一个新的 Content-Type 头部字段:

const headers = new Headers();
headers.append('Content-Type', 'application/json');

这样,headers 对象中就添加了一个 Content-Type: application/json 的头部字段。如果要添加多个值,则可以多次调用 append() 方法,或者在值中使用逗号分隔。
注意,Headers.append() 方法不会删除相同名称的头部字段,而是将新的值追加到现有的值列表中。假设我们需要发送一个 HTTP 请求头部,包含多个值的键,我们可以使用 Headers.append() 方法将值追加到现有的值列表中。例如:

const headers = new Headers();
headers.append('Accept-Language', 'en-US');
headers.append('Accept-Language', 'fr-FR');
headers.append('Accept-Language', 'de-DE');
console.log(headers.get('Accept-Language')); // "en-US, fr-FR, de-DE"

在这个例子中,我们创建了一个新的 Headers 对象,然后使用 append() 方法三次添加了 Accept-Language 键的三个值。由于这个键在每个 append() 调用中都是相同的,因此每个新值都被追加到现有的值列表中。最后,我们使用 get() 方法检索该键的值,该方法返回一个字符串,其中包含所有值,值之间以逗号和空格分隔。如果要覆盖现有的值,可以使用 Headers.set() 方法。

Headers.prototype.set()

Headers.prototype.set() 方法用于将一个指定的头部和它的值追加到 Headers 对象的末尾,如果头部已经存在则替换它的值。
语法:
headers.set(name, value);
参数:
name: 要设置的头部的名称
value: 要设置的头部的值
示例:

const headers = new Headers();
headers.set('Content-Type', 'application/json');
console.log(headers.get('Content-Type')); // "application/json"
headers.set('Content-Type', 'text/html');
console.log(headers.get('Content-Type')); // "text/html"

在这个例子中,首先使用 set() 方法将 Content-Type 头部设置为 application/json。然后调用 get() 方法来获取头部的值,并输出它。接着再次使用 set() 方法将 Content-Type 头部设置为 text/html,这次是替换之前的值。最后再次使用 get() 方法获取头部的值,并输出它。

Headers.prototype.get()

Headers.prototype.get() 方法用于获取给定头部名称的第一个值。如果不存在该名称,则返回 null。
下面是一个例子,展示如何使用 get() 方法从头部中获取指定名称的值:

const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer abc123');
headers.append('Authorization', 'Basic xyz456');

const contentType = headers.get('Content-Type');
console.log(contentType); // 输出:application/json

const authorization = headers.get('Authorization');
console.log(authorization); // 输出:Bearer abc123

在这个例子中,我们首先创建了一个新的 Headers 对象,并使用 append() 方法向其添加了三个不同的头部。然后,我们使用 get() 方法从头部中获取了 Content-Type 和 Authorization 的值。注意,由于头部中存在两个 Authorization 值,get() 方法只返回了第一个值,即 Bearer abc123。

Headers.prototype.delete()

Headers.prototype.delete()用于删除 Headers 对象中指定的头部信息。该方法接收一个参数,即要删除的头部信息的名称,然后从 Headers 对象中删除指定名称的头部信息。如果 Headers 对象中不存在该名称的头部信息,则该方法不执行任何操作。例如,下面的代码展示了如何使用 delete() 方法从 Headers 对象中删除名为 “Content-Type” 的头部信息:

const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Bearer abc123'
});

headers.delete('Content-Type');

console.log(headers.get('Content-Type')); // null
console.log(headers.get('Authorization')); // "Bearer abc123"

在上面的示例中,首先创建了一个包含两个头部信息的 Headers 对象,然后使用 delete() 方法删除了 “Content-Type” 头部信息。最后,使用 get() 方法验证 “Content-Type” 头部信息已被删除。

Headers.prototype.has()

Headers.prototype.has() 方法用于判断 Headers 对象中是否存在指定名称的头信息。如果存在则返回 true,否则返回 false。
该方法接受一个参数,即要查找的头信息名称。示例如下:

const headers = new Headers({
  'Content-Type': 'application/json',
  'X-Custom-Header': 'custom-value'
});

console.log(headers.has('Content-Type')); // true
console.log(headers.has('X-Custom-Header')); // true
console.log(headers.has('Authorization')); // false

在上面的示例中,我们首先创建了一个包含两个头信息的 Headers 对象,然后使用 has() 方法来查找指定的头信息名称。第一个和第二个调用都会返回 true,因为该对象中包含了这两个头信息;而第三个调用则会返回 false,因为该对象中不包含指定的头信息名称。

keys(), values(), entries()

这三个方法都返回一个迭代器对象,keys()返回所有的header名称,values()返回所有的header值,entries()返回所有的键值对,例如:

const headers = new Headers({
  'Content-Type': 'application/json',
  'X-My-Header': 'foo'
});

for (const key of headers.keys()) {
  console.log(key);
}
// content-type
// x-my-header

for (const key of headers.values()) {
  console.log(key);
}
// application/json
// foo

for (const [key, value] of headers.entries()) {
  console.log(key, value);
}
// content-type application/json
// x-my-header foo

通过这个例子我们还能够发现一个问题就是header的key值是不区分大小写的,也就是说,例如Content-Type和content-type是等价的,服务端接收到这两个字段时会视作同一个字段进行处理。在 JavaScript 中,Headers 类的方法也遵循了这个规范,可以忽略头字段名的大小写来进行操作。

Headers.prototype.forEach()

Headers.prototype.forEach()用于迭代遍历头信息中所有的键值对,可以接收一个回调函数作为参数。
函数原型为:
Headers.prototype.forEach(callback, thisArg);
其中,callback 表示回调函数,接收三个参数:
value:当前遍历到的值;
key:当前遍历到的键;
headers:当前的 Headers 对象。
而 thisArg 表示可选参数,用于指定 callback 函数中 this 的值。
例如:

Headers.prototype.forEach(callback, thisArg);

const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Bearer token123'
});

headers.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});

输出结果为:

content-type: application/json
authorization: Bearer token123

原文链接:https://juejin.cn/post/7244530183049674812 作者:前端良文

(0)
上一篇 2023年6月17日 上午10:53
下一篇 2023年6月17日 上午11:03

相关推荐

发表回复

登录后才能评论