fetch 传统 Web 应用程序中大多数 XMLHttpRequest 的可行替代方案

发布于 2020-10-11 16:44:18 字数 7799 浏览 2071 评论 0

这个 fetch() 函数是一种在浏览器中以编程方式发出 Web 请求的基于 Promise 的机制。此项目是一个实现标准子集的PolyFill。足以使 fetch 传统 Web 应用程序中大多数 XMLHttpRequest 的可行替代方案。

阅前须知

1、如果你再使用中发现了一个问题,请不要急着提交 Issues,不要在这个项目中打开一个问题除非您在不支持的旧版本浏览器中进行测试 window.fetch。一定要看这个自述文件,特别是 警告 部分,可能有一个已知的解决问题的方法。

2、如果你有麻烦 向另一个域提出请求,不同的子域或端口号也构成另一个域,请熟悉 CORS 请求规范。因为 CORS 需要服务器通过实现特定的 HTTP 响应头来参与,所以设置或调试通常是非常重要的。CORS 完全由浏览器的内部机制处理,这种填充不会影响这些机制。

3、这个项目 在 Node.js 环境下不工作。它只适用于网页浏览器。您应该确保您的应用程序不会试图在服务器上打包和运行这个包。

4、如果您有一个新功能的想法 fetch, 提交功能请求规范存储库

安装

npm install whatwg-fetch --save

作为使用 npm 的替代方案,您可以fetch.umd.js。UMD 发行版与 AMD 和 CommonJS 模块加载器兼容,并通过 <script> 标签。

你还需要一个 Promise 兼容解决方案,我们建议 taylorhakes/promise-polyfill 体积小,并且和 Promises/A+ 完全兼容。

使用方法

引入

引入后将自动注册 window.fetch 及有关的 APIs:

import 'whatwg-fetch'
window.fetch(...)

如果出于某种原因,您需要访问PolyFill实现,则可以通过导出获得该实现:

import {fetch as fetchPolyfill} from 'whatwg-fetch'

window.fetch(...)   // use native browser version
fetchPolyfill(...)  // use polyfill implementation

例如,这种方法可用于中止功能在实现本机但过时版本的FETCH的浏览器中,不支持中止。

若要与webpack一起使用,请将此包添加到entry在应用程序入口点之前的配置选项:

entry: ['whatwg-fetch', ...]

HTML

fetch('/users.html')
  .then(function(response) {
    return response.text()
  }).then(function(body) {
    document.body.innerHTML = body
  })

JSON

fetch('/users.json')
  .then(function(response) {
    return response.json()
  }).then(function(json) {
    console.log('parsed json', json)
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })

响应元数据

fetch('/users.json').then(function(response) {
  console.log(response.headers.get('Content-Type'))
  console.log(response.headers.get('Date'))
  console.log(response.status)
  console.log(response.statusText)
})

Post Table

var form = document.querySelector('form')

fetch('/users', {
  method: 'POST',
  body: new FormData(form)
})

Post JSON

fetch('/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

文件上传

var input = document.querySelector('input[type="file"]')

var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')

fetch('/avatars', {
  method: 'POST',
  body: data
})

警告

  • 许下的诺言 fetch() 不会拒绝HTTP错误状态即使响应是HTTP 404或500。相反,它将正常地解决,并且它只会拒绝网络故障或任何阻止请求完成的事情。
  • 为了在发送和接收cookie时获得最大的浏览器兼容性,请始终提供 credentials: 'same-origin' 选项,而不是依赖于默认设置。
  • 在这个多边形填充中并不支持所有的提取标准选项。例如 redirectcache 指令被忽略。
  • keepalive 不受支持,因为它涉及到同步的XHR,这是这个项目不愿意做的事情。

处理 HTTP 错误状态

fetch承诺拒绝HTTP错误状态,即在任何非2xx状态下,定义一个自定义响应处理程序:

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  } else {
    var error = new Error(response.statusText)
    error.response = response
    throw error
  }
}

function parseJSON(response) {
  return response.json()
}

fetch('/users')
  .then(checkStatus)
  .then(parseJSON)
  .then(function(data) {
    console.log('request succeeded with JSON response', data)
  }).catch(function(error) {
    console.log('request failed', error)
  })

发送 Cookies

CORS 请求,使用 credentials: 'include' 要允许向其他域发送凭据,请执行以下操作:

fetch('https://example.com:1234/users', {
  credentials: 'include'
})

的默认值 credentials 是 same-origin。

默认的credentials但并不总是一样的。以下版本的浏览器实现了一个旧版本的FETCH规范,默认情况是 omit:

  • Firefox 39-60
  • Chrome 42-67
  • Safari 10.1-11.1.2

如果以这些浏览器为目标,建议始终指定 credentials: 'same-origin' 显式地处理所有FETCH请求,而不是依赖默认的:

fetch('/users', {
  credentials: 'same-origin'
})

注:应付 XMLHttpRequest的局限性,使用 credentials: 'omit' 在浏览器中,对于相同的域,此多边形填充是活动的,则不受尊重。在旧浏览器中,cookie将始终发送到相同的域。

接收 Cookies

与 XMLHttpRequest 一样,Set-Cookie 从服务器返回的响应标头是 禁止标头名 因此无法以编程方式读取 response.headers.get()。相反,浏览器有责任处理正在设置的新 Cookie,如果适用于当前 URL。除非它们仅限于 HTTP,否则新的 Cookie 将通过 document.cookie

Redirect modes

The Fetch specification defines these values for the redirect option: "follow" (the default), "error", and "manual".

Due to limitations of XMLHttpRequest, only the "follow" mode is available in browsers where this polyfill is active.

获取响应 URL

由于XMLHttpRequest的限制,response.url HTTP在旧浏览器上重定向后,该值可能不可靠。

解决方案是配置服务器以设置响应HTTP报头 X-Request-URL 在可能发生的任何重定向之后,转到当前 URL。无条件地设置它应该是安全的。

# Ruby on Rails controller example
response.headers['X-Request-URL'] = request.url

如果您需要可靠,此服务器解决方案是必要的。response.url 在 Firefox<32,Chrome<37,Safari 或 IE 中。

中止请求

这种填充支架可中止的获取API。但是,中止获取需要使用两个额外的DOMAPI:AbortControllerAbortSignal。通常,不支持FETCH的浏览器也不支持AbortController或AbortSignal。因此,您需要包括一种额外的填充要使这些API中止获取,请执行以下操作:

import 'yet-another-abortcontroller-polyfill'
import {fetch} from 'whatwg-fetch'

// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch

const controller = new AbortController()

abortableFetch('/avatars', {
  signal: controller.signal
}).catch(function(ex) {
  if (ex.name === 'AbortError') {
    console.log('request aborted')
  }
})

// some time later...
controller.abort()

浏览器支持

  • Chrome
  • Firefox
  • Safari 6.1+
  • Internet Explorer 10+

注意:诸如 Chrome、Firefox、MicrosoftEdge 和 Safari 等现代浏览器包含 window.fetch 。因此,这种 polyfill 的代码对这些浏览器没有任何影响。如果你认为你遇到了一个错误 window.fetch 是在任何这些浏览器中实现的,您应该向该浏览器供应商提交一个问题,而不是该项目。

相关链接

github 地址:https://github.com/github/fetch

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

lorenzathorton8

文章 0 评论 0

Zero

文章 0 评论 0

萧瑟寒风

文章 0 评论 0

mylayout

文章 0 评论 0

tkewei

文章 0 评论 0

17818769742

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文