【JavaScript API】 fetch 用法详解

627 阅读5分钟

前言

全局的 fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。
考虑低版本浏览器的问题的话,引入github.com/github/fetc… 即可兼容。

语法

Promise<Response> fetch(url, optionObj)

Request

  • method: 请求使用的方法,如 GET、POST。
  • headers: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。
  • body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  • mode: 请求的模式:
    1. cors:默认值,允许跨域请求。
    2. same-origin:只允许同源请求。
    3. no-cors:请求方法只限于 GET、POST 和 HEAD,并且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求
  • credentials: 请求的 credentials:
    1. same-origin:默认值,同源请求时发送 Cookie,跨域请求时不发送。
    2. include:不管同源请求,还是跨域请求,一律发送 Cookie。
    3. omit:一律不发送。
  • cache: 请求的 cache 模式:
    1. default:默认值,先在缓存里面寻找匹配的请求。
    2. no-store:直接请求远程服务器,并且不更新缓存。
    3. reload:直接请求远程服务器,并且更新缓存。
    4. no-cache:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存。
    5. force-cache:缓存优先,只有不存在缓存的情况下,才请求远程服务器。
    6. only-if-cached:只检查缓存,如果缓存里面不存在,将返回504错误。
  • redirect: 可用的 redirect 模式:
    1. follow (自动重定向)
    2. error (如果产生重定向将自动终止并且抛出一个错误),
    3. manual (手动处理重定向)。在 Chrome 中默认使用 follow(Chrome 47 之前的默认值是 manual)。
  • referrer: 一个 USVString 可以是 no-referrer、client 或一个 URL。默认是 client。
  • referrerPolicy: 指定了 HTTP 头部 referer 字段的值:
    1. no-referrer-when-downgrade:默认值,总是发送Referer标头,除非从 HTTPS 页面请求 HTTP 资源时不发送。
    2. no-referrer:不发送Referer标头。
    3. origin:Referer标头只包含域名,不包含完整的路径。
    4. origin-when-cross-origin:同源请求Referer标头包含完整的路径,跨域请求只包含域名。
    5. same-origin:跨域请求不发送Referer,同源请求发送。
    6. strict-origin:Referer标头只包含域名,HTTPS 页面请求 HTTP 资源时不发送Referer标头。
    7. strict-origin-when-cross-origin:同源请求时Referer标头包含完整路径,跨域请求时只包含域名,HTTPS 页面请求 HTTP 资源时不发送该标头。
    8. unsafe-url:不管什么情况,总是发送Referer标头。
  • integrity: 指定一个哈希值,用于检查 HTTP 回应传回的数据是否等于这个预先设定的哈希值。
  • signal: 指定一个 AbortSignal 实例,用于取消fetch()请求
  • keepalive:用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
const headers = new Headers({
  // "Content-Type": "text/plain;charset=UTF-8"
  // 'Content-Type': 'application/json' // json
  'Content-Type': 'application/x-www-form-urlencoded' // 发送表单数据
})
const response = fetch(url, {
  method: "GET",//请求方式
  // headers: {//定制http请求的标头
  //   'Content-Type': 'application/x-www-form-urlencoded' // 发送表单数据
  // },
  headers, //定制http请求的标头
  body: undefined,//post请求的数据体,因为此时为get请求,故为undefined
  referrer: "about:client",
  referrerPolicy: "no-referrer-when-downgrade",//用于设定fetch请求的referer标头
  mode: "cors", //指定请求模式,此时为cors表示支持跨域请求
  credentials: "same-origin",//发送cookie
  cache: "default",//指定如何处理缓存
  redirect: "follow",
  integrity: "",
  keepalive: false,
  signal: undefined 
})

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 的类型(例如,basic、cors)。
  • Response.url 只读

方法:

  • text():得到文本字符串,用于获取文本数据,比如 HTML 文件。
  • json():得到 JSON 对象。
  • blob():得到二进制 Blob 对象,例如读取图片文件,显示在网页上。
  • formData():得到 FormData 表单对象,主要用在 Service Worker 里面,拦截用户提交的表单,修改某些数据以后,再提交给服务器。
  • arrayBuffer():得到二进制 ArrayBuffer 对象,主要用于获取流媒体文件。

Stream 对象只能读取一次,读取完就没了,这意味着五个读取方法,只能使用一个,否则会报错。

  • Response 对象提供Response.clone()方法,创建Response对象的副本,实现多次读取。
let text =  await response.text()
let json =  await response.json()  // 报错
const response1 = await fetch('请求的url');
// response.clone()复制了一份 Response 对象
const response2 = response1.clone()

const myBlob1 = await response1.text()
const myBlob2 = await response2.json()

判断请求是否成功发出

第一种方法:

  • fetch()发出请求以后,只有网络错误或者无法连接时,fetch()才会报错,其他情况都不会报错,而是认为请求成功。
  • 只有通过Response.status属性,得到HTTP 回应的真实状态码,才能判断请求是否成功

第二种方法:

  • 判断response.ok是否为true

取消请求

fetch()请求发送后,如果中途想要取消,需要使用AbortController对象

//创建实例
let controller = new AbortController()
//设置定时器, 取消
setTimeout(() => controller.abort(), 1000)

try {
  let response = await fetch('路径', {
    signal: controller.signal
  })
} catch(err) {
  if (err.name == 'AbortError') {
    console.log('Aborted!')
  } else {
    throw err
  }
}