对于成功的同源请求,Fetch 会抛出“TypeError: Failed to fetch”

Posted

技术标签:

【中文标题】对于成功的同源请求,Fetch 会抛出“TypeError: Failed to fetch”【英文标题】:Fetch throws "TypeError: Failed to fetch" for successful, same-origin request 【发布时间】:2018-10-29 07:59:27 【问题描述】:

在单页 javascript 应用程序发出提取请求时,我们遇到了不一致的客户端错误。值得注意的是,它们都是 same-origin 请求。

let request = new Request(url, options);
...
window.fetch(request)
  .then(response => response.json())
  .then(data => ...)
  .catch(error => ...)

尽管服务器和浏览器收到了200 OK 响应,但仍有大约 5% 的 Promise 被拒绝并出现以下错误:

TypeError: Failed to fetch

我很难过...我所有的搜索都会引发关于 CORS 错误的讨论。鉴于这些都是同源请求,这似乎并不适用。是什么导致 fetch 抛出 TypeError

我可以使用 Chrome DevTools 中的“网络”选项卡确认获取请求已完成,并带有 200 OK 响应和有效的 JSON。我还可以确认 URL 是同源的。我还可以确认没有 CORS 飞行前请求。我已经在 Chrome 66 和 Safari 11.1 上重现了这个问题。但是,我们收到了来自桌面版和移动版 Chrome 和 Safari 混合版本的一系列错误报告。


编辑:

这似乎不是链接问题的重复,因为我们发送 CORS 请求,设置mode: "no-cors" em> 设置Access-Control-Allow-Origin 标头。

此外,我使用明确设置的mode: 'same-origin' 选项重新运行测试。请求(仍然)成功;但是,我们(仍然)收到间歇性的TypeError

【问题讨论】:

您在options 中使用mode: "no-cors" 吗?见***.com/questions/42754388/… @Barmar 我确实设置mode 选项。看起来默认的modecors (developer.mozilla.org/en-US/docs/Web/API/Request/mode)。不确定这在同源请求的上下文中意味着什么。但是,我可以通过显式使用mode: same-origin 重新测试和更新线程。 Uncaught (in promise) TypeError: Failed to fetch and Cors error的可能重复 @Mr.White 我通读了那个问题......接受的答案谈到了 CORS 标头和飞行前请求。这些不会发生在我的同源请求中。此外,该问题的 cmets 对该问题有 real 的答案:“我认为,如果您从请求中删除访问控制标头并且不添加模式,您的所有问题都会消失:'不接受请求”。我已经确认这就是我的请求的构造方式。 我找不到任何其他不涉及该选项的错误解释。 【参考方案1】:

我知道这是一个老问题,但是在搜索了整个晚上后,我想分享我的发现,以便您可以更好地度过时间。

我的网络应用程序对大多数用户来说也运行良好,但有时访问者会收到问题中提到的错误。我没有使用任何复杂的基础设施(反向代理等)设置,也没有与不同域/协议/端口上的服务进行通信。我只是向提供 React 应用程序的同一服务器上的 php 文件发送 POST 请求。

简短的回答:我的问题是我使用绝对 URL 将请求发送到后端,例如 https://my-fancy-domain.com/funky_service.php。将其更改为 /funky-service.php 之类的相对路径后,问题就消失了。

我的解释:大多数用户访问该站点时 URL 中没有 www,但有些用户实际上确实在地址栏中输入了这部分 (www.my-fancy...)。原来,www 是来源的一部分,所以当这些用户提交表单并向 https://my-fancy 发送帖子请求时……从技术上讲,它是另一个来源。这就是为什么浏览器需要 CORS 标头,有时甚至会发送一个 OPTIONS 预检请求。当您在 JavaScript 代码中使用相对路径时,发布请求还将包括 www 部分(使用地址栏中的来源)-> 同源-> 没有 CORS 麻烦。由于它只影响带有 www 访问您网站的访问者,因此它也说明了即使使用绝对 URL,它也适用于大多数用户。

同样重要的是要知道:请求在浏览器/JavaScript 代码中失败,但实际上被发送到后端(非常丑陋!)。

如果您需要更多信息,请告诉我。实际上,它很简单,但很难解释(也很难找到)

【讨论】:

【参考方案2】:

问题可能与您从后端收到的响应有关。如果它在服务器上运行良好,那么问题可能出在响应标头上。检查响应标头中的 Access-Control-Allow-Origin (ACAO)。通常react的fetch API在response headers的ACAO和request的来源不匹配的情况下,即使收到response也会抛出fail to fetch。

参考:Getting "TypeError: failed to fetch" when the request hasn't actually failed

【讨论】:

是的,CORS 应用程序的故障排除步骤非常好。在我们的例子中,这是一个同源请求。 你浏览评论中的链接了吗?

以上是关于对于成功的同源请求,Fetch 会抛出“TypeError: Failed to fetch”的主要内容,如果未能解决你的问题,请参考以下文章

android的React Native fetch()网络请求失败?

React Native fetch() 在 Android 7 上抛出“网络请求失败”,但在 Android 6 上运行良好

Hibernate LAZY fetch [重复]

React Fetch 到 Laravel API 创建新会话

嵌套的 try、catch 和 async、await 请求

仅当URL变为LONG时,ORA-29263才会抛出错误