当请求实际上没有失败时,获取“TypeError:无法获取”

时间:2018-03-17 23:38:03

标签: javascript get fetch

我在我的React应用中使用fetch API。该应用程序部署在服务器上,运行正常。我多次测试了它。但是,突然应用程序停止工作,我不知道为什么。问题是,当我发送get请求时,我收到服务器的有效响应,但fetch API正在捕获异常并显示TypeError: failed to fetch。我甚至没有对代码进行任何更改,这是所有React组件的问题。

我收到了有效回复。

enter image description here

但同时也会出现此错误。

enter image description here

fetch(url)
.then(res => res.json())
.then(data => {
  // do something with data
})
.catch(rejected => {
    console.log(rejected);
});

当我删除credentials: "include"时,它适用于localhost,但不适用于服务器。

我尝试了在StackOverflow和GitHub上给出的每个解决方案,但这对我来说不合适。

8 个答案:

答案 0 :(得分:13)

问题可能在于您从后端收到的回复。如果它在服务器上正常工作,那么问题可能在于响应头。 检查响应标头中的 Access-Control-Allow-Origin (ACAO)。通常,当响应标头的ACAO和请求的来源不匹配时,即使在收到响应后,react的fetch API也将无法获取。

答案 1 :(得分:13)

我知道这个问题可能有特定于 React 的原因,但它首先出现在“Typeerror: Failed to fetch”的搜索结果中,我想在这里列出所有可能的原因。

Fetch 规范列出了您从 Fetch API 抛出 TypeError 的次数:https://fetch.spec.whatwg.org/#fetch-api

截至 2021 年 1 月的相关段落如下。这些是正文的摘录。

4.6 HTTP 网络获取

<块引用>

要使用带有可选凭据标志的请求执行 HTTP 网络提取,请运行以下步骤:
...
16. 并行运行这些步骤:
...
2.如果中止,则:
...
3. 否则,如果流可读,则错误流为 TypeError。

<块引用>

要将名称/值名称/值对附加到 Headers 对象(标头),请运行以下步骤:

  1. 标准化值。
  2. 如果 name 不是名称或 value 不是值,则抛出 TypeError。
  3. 如果 headers 的守卫是“不可变的”,那么抛出一个 TypeError。

使用给定的对象对象填充标题对象标题:

<块引用>

要使用给定的对象对象填充 Headers 对象标题,请运行以下步骤:

  1. 如果 object 是一个序列,那么对于 object 中的每个标头:
    1. 如果 header 不包含正好两个项目,则抛出 TypeError。

方法步骤有时会抛出 TypeError:

<块引用>

delete(name) 方法步骤是:

  1. 如果 name 不是名称,则抛出 TypeError。
  2. 如果这个守卫是“不可变的”,那么抛出一个类型错误。
<块引用>

get(name) 方法步骤是:

  1. 如果 name 不是名称,则抛出 TypeError。
  2. 返回从 t​​his 的头部列表中获取 name 的结果。
<块引用>

has(name) 方法步骤是:

  1. 如果 name 不是名称,则抛出 TypeError。
<块引用>

set(name, value)方法步骤为:

  1. 标准化值。
  2. 如果 name 不是名称或 value 不是值,则抛出 TypeError。
  3. 如果这个守卫是“不可变的”,那么抛出一个类型错误。
<块引用>

要从对象中提取主体和 Content-Type 值,使用可选的布尔值 keepalive(默认为 false),请运行以下步骤:
...
5. 开启对象:
...
可读流
如果 keepalive 为真,则抛出 TypeError。
如果对象受到干扰或锁定,则抛出 TypeError。

在“Body mixin”部分,如果您使用 FormData,有几种方法可以抛出 TypeError。我没有在这里列出它们,因为它会使这个答案很长。相关段落:https://fetch.spec.whatwg.org/#body-mixin

在“请求类”部分中,新的 Request(input, init) 构造函数是潜在类型错误的雷区:

<块引用>

新的Request(input, init)构造器步骤为:
...
6. 如果输入是字符串,则:
...
2. 如果 parsedURL 失败,则抛出 TypeError。
3. 如果 parsedURL 包含凭据,则抛出 TypeError。
...
11. 如果 init["window"] 存在且非空,则抛出 TypeError。
...
15.如果init["referrer"存在,则:
...
1.让referrer为init["referrer"].
2. 如果referrer为空字符串,则设置request的referrer为“no-referrer”。
3. 否则:
1.让parsedReferrer为baseURL解析referrer的结果。
2. 如果parsedReferrer失败,则抛出TypeError。
...
18.如果模式是“导航”,则抛出一个TypeError。
...
23.如果请求的缓存模式是“only-if-cached”并且请求的模式不是“same-origin”,那么抛出一个TypeError。
...
27.如果init["method"]存在,则:
...
2.如果method不是方法或者method是禁止方法,则抛出TypeError。
...
32.如果这个请求的模式是“no-cors”,则:
1. 如果这个请求的方法不是 CORS 安全列表方法,则抛出 TypeError。
...
35. 如果 init["body"] 存在且为非空或 inputBody 为非空,并且请求的方法为 GETHEAD,则抛出 TypeError。
...
38.如果body为非空且body的源为null,则:
1.如果这个请求的模式既不是“同源”也不是“cors”,那么抛出一个TypeError。
...
39. 如果 inputBody 是 body 并且 input 被干扰或锁定,则抛出 TypeError。

<块引用>

clone() 方法步骤是:

  1. 如果这被干扰或锁定,则抛出 TypeError。

在响应类中:

<块引用>

新的Response(body, init)构造器步骤是:
...
2. 如果 init["statusText"] 与原因短语标记产生不匹配,则抛出 TypeError。
...
8.如果body为非空,则:
1. 如果 init["status"] 是 null body 状态,则抛出 TypeError。
...

<块引用>

静态redirect(url, status)方法步骤为:
...
2. 如果 parsedURL 失败,则抛出 TypeError。

<块引用>

clone() 方法步骤是:

  1. 如果这被干扰或锁定,则抛出 TypeError。

在“获取方法”部分

<块引用>

fetch(input, init)方法步骤为:
...
9. 并行运行以下:
要处理响应响应,请运行以下子步骤:
...
3. 如果响应是网络错误,则以 TypeError 拒绝 p 并终止这些子步骤。

除了这些潜在问题之外,还有一些特定于浏览器的行为可能会引发 TypeError。例如,如果您将 keepalive 设置为 true 并且有效负载 > 64 KB,您将在 Chrome 上收到 TypeError,但相同的请求可以在 Firefox 中工作。这些行为未记录在规范中,但您可以通过谷歌搜索找到有关您在 fetch 中设置的每个选项的限制的信息。

答案 2 :(得分:3)

我知道这是一个相对较旧的职位,但是,我想分享对我有用的内容: 我只是在URL中的“ localhost”之前输入“ http://”。希望对别人有帮助。

答案 3 :(得分:2)

请注意,您的代码中存在一个不相关的问题,但稍后会引起您的注意:您应该return res.json()或者您不会发现JSON解析或您自己的函数处理数据中发生的任何错误。

返回错误:无法拥有成功请求的TypeError: failed to fetch。您可能有另一个请求(检查您的&#34;网络&#34;面板以查看所有这些请求)中断并导致记录此错误。此外,也许,检查&#34;保留日志&#34;确保面板不会被任何不正确的重定向清除。有时我碰巧有一个持久的&#34;控制台&#34;面板和清除的网络&#34;导致我在控制台中出错的面板实际上与可见请求无关。你应该检查一下。

或者你(但那会很恶毒)实际上在你的最终console.log('TypeError: failed to fetch')中有一个硬编码的.catch;并且错误在你的.then()中实际存在但是它已经存在很难相信。

答案 4 :(得分:1)

如果要在本地主机服务器上调用访存,请使用非SSL协议,除非您具有本地主机的有效证书。对于无效或自签名证书,尤其是在本地主机上,获取将失败。

答案 5 :(得分:1)

就我而言,我在使用 jsfiddle 或 stackblitz 等在线 JS 工具时遇到了“TypeError”,问题是我的 url 是 http 而不是 https。

答案 6 :(得分:0)

我有一个类似的问题,由于我是新手,因此有一些事实可供人们评论:

我正在以这种方式向Google工作表发送表单数据(scriptURL为https://script.google.com/macros/s/AKfy ..., showSuccess()显示的是简单图像):

fetch(scriptURL, {method: 'POST', body: new FormData(form)})
.then(response => showSuccess())
.catch(error => alert('Error! ' + error.message))

在Edge中执行时,我的HTML没有显示错误,并且“网络”标签报告了这3个请求: Edge execution 在Chrome中执行的我的HTML(index.htm)显示无法提取错误,并且“网络”标签报告了这2个请求: Chrome execution 第二列的值是 blocked:other ,并且“控制台”选项卡中也存在错误:

获取https://script.googleusercontent.com/macros/echo?user_content_key=D-ABF ... 净:: ERR_BLOCKED_BY_CLIENT

为了暂停已安装的Chrome扩展程序,我在隐身窗口中执行了我的代码,没有错误消息,并且“网络”标签报告了这2个请求: Incognito execution

我的猜测是,某些内容(扩展名?)阻止Chrome浏览器读取请求的答案(GET请求被阻止)。

答案 7 :(得分:0)

在幕后,XHR 客户端发送一个 HTTPOPTIONS 请求,称为 pre-flight,以查找某些安全权限标头,称为 CORS Allow 标头。如果未找到所需的标头(因为您可能没有必要的权限),则结果为 TypeError,因为它实际上并未尝试发送您的 POST/GET 请求。您可以在浏览器控制台中观察这种行为:看起来浏览器向同一位置发出了两个请求,首先是 HTTP 方法:OPTIONS。