为什么在`fetch`中触发`catch`取决于我在第一个`then`中如何返回响应?

时间:2018-01-19 14:35:12

标签: javascript error-handling try-catch fetch

考虑以下代码:

fetch('https://www.reddit.com/r/javascript/json')
  .then(res => res.text())
  .then(() => {
    console.log('SUCCESS');
  })
  .catch(err => {
    console.log('FAIL');
  })

它故意是错误的路线,并且它返回代码404的错误。但是,SUCCESS情况正在触发。

但是,如果我将res => res.text()替换为res => res.json(),则会捕获FAIL,因为它应该是。{/ p>

此外,即使使用FAIL,放置绝对错误的网址(我的意思是不存在的服务器)也会导致正确的导线res.text()

我发现这种行为有点奇怪和棘手,并且会感激一些澄清。

P上。 S.我知道,这可能有助于这一预防措施:if (!res.ok) throw new Error();,只是好奇为什么会这样做。

2 个答案:

答案 0 :(得分:3)

  

它故意是错误的路线并且它返回代码404的错误。但是,SUCCESS案例正在触发。

这是设计的。 fetch调用仅承诺发出请求并返回响应 - 任何响应。只有在出现网络问题时才会拒绝,例如更改域时不存在的服务器。

状态代码或正文内容在确定其是否有效的HTTP响应时无关紧要。要检查其状态是否成功,您必须按照您的说明测试res.ok

  

但是,如果我将res => res.text()替换为res => res.json(),它会按照原样捕获失败。

是的,但那并不是因为请求失败了。它抛出是因为你的响应体不是有效的JSON - 它甚至可以与404一起使用。

答案 1 :(得分:2)

简短回答是您的承诺在res.json()

上犯了错误

长答案(解释)

您的初始http调用成功,因此执行“成功”承诺

  • 这是因为url存在并以成功的状态代码响应并返回由字符串/文本表示的html页面
  • 它返回的响应只是页面的文字表示,恰好显示文本“找不到页面”,但您的调用状态才能获得 >页面不是404,它实际上是200,或者你将无法看到页面......(相当精神弯曲)

但是...... 即使你的电话实际上是成功的,当Promise中的任何地方抛出未处理的错误时,你总是会触发'失败'的承诺( catch ),这就是承诺的运作方式。

现在.... 基本上uri会返回html页面的文字表示,因此调用res.text()成功,但是当您在'text'上调用res.json()时数据它会抛出一个错误,因为响应不是json,并且该错误会冒泡并最终被承诺的捕获所捕获。如果你想要json,你必须首先知道你希望从你的响应中获得的数据类型,然后转换成你想要的。

课程这里知道您的返回类型,以便您了解期望和代码的内容,调用uri并且不知道它返回的数据类型是没有意义的。