fetch 即使 404 也能解决?

Posted

技术标签:

【中文标题】fetch 即使 404 也能解决?【英文标题】:fetch resolves even if 404? 【发布时间】:2017-01-10 20:41:07 【问题描述】:

使用此代码:

fetch('notExists') // <---- notice 
    .then(
        function(response)
        
           alert(response.status)
        
    )
    .catch(function(err)
    
       alert('Fetch Error : ', err);
    );

这个承诺解决

mdn

它返回一个可以解析为该请求的响应的承诺, 不管成功与否。

一个失败的 ajax 请求即使转到一个不存在的资源也得到了解决,这不是很奇怪吗?

我的意思是——接下来呢?将fetch 发送到已关闭但仍获得已解决承诺的服务器?

我知道我可以在 response 对象的 ok 属性上进行调查,但仍然 -

问题

为什么会为完全错误的请求(非现有资源)解决提取问题。

BTW , jquery request , does get rejected

【问题讨论】:

它必须解决才能处理错误代码。 @Barmar 那么为什么不在 catch/reject 处理程序上呢? 您希望获取标准的作者回复吗?因为他们将是那些无需猜测就能回答这个问题的人。 @MikeMcCaughan 我只是想找到答案。我不希望 Henrik 在这里回答 :-) 我同意,404 不走错误路径是疯狂的。 【参考方案1】:

拒绝处理程序用于网络和 CORS 错误 iirc。如果请求到达服务器并以有效的 http 响应进行响应,则即使响应代码为 4xx 或 5xx,promise 也会得到满足。

【讨论】:

【参考方案2】:

fetch() 调用仅在网络请求本身因某种原因失败(未找到主机、未连接、服务器未响应等...)时才会被拒绝。

从承诺的角度来看,从服务器返回的任何结果(404、500 等...)都被视为成功请求。从概念上讲,您从服务器发出请求,服务器响应您,因此从网络的角度来看,请求成功完成。

然后您需要测试该成功响应以查看是否有您想要的答案类型。如果您希望 404 被拒绝,您可以自己编写代码:

fetch('notExists').then(function(response) 
    if (!response.ok) 
        // make the promise be rejected if we didn't get a 2xx response
        const err = new Error("Not 2xx response");
        err.response = response;
        throw err;
     else 
         // go the desired response
    
).catch(function(err) 
    // some error here
);

您甚至可以创建自己的 myFetch(),它会自动为您执行此操作(将任何非 200 响应状态转换为拒绝)。

已解决的承诺背后的原因是什么? 请求(非现有资源/服务器停机)。

首先,服务器关闭不会产生成功的响应 - 会拒绝。

如果您成功连接到服务器,向其发送请求并返回响应(任何响应),则会生成成功响应。至于“为什么”fetch() 界面的设计者决定以此为由拒绝,如果不与实际参与该界面设计的人交谈,就很难说,但对我来说这似乎是合乎逻辑的。通过这种方式,拒绝会告诉您请求是否通过并得到有效响应。由您的代码决定如何处理响应。当然,您可以创建自己的包装函数来修改默认行为。

【讨论】:

哦,好吧,我知道没有地方可以比较,但 $.ajax//a 确实被拒绝了。 jsbin.com/pukurolego/1/edit?html,js,output @RoyiNamir - 我不认为你是 jsbin 的例子正在做你认为的事情。如果我console.log() 拒绝错误,我会看到这个Failed to load resource: net::ERR_ADDRESS_UNREACHABLE http://0.0.0.22/。我不确切知道 jQuery 的行为方式,但你的 jsbin 没有测试正确的东西。 你说得对,我的错,没看到。我需要休息。【参考方案3】:

使用此代码...

fetch(`https://fercarvo.github.io/apps/integradora/DB/corpus.json`)
.then(async (data) => 
    if (data.ok) 
        data = await data.json()
        //Here you have your data...
    
).catch(e => console.log('Connection error', e))

【讨论】:

【参考方案4】:

以@fernando-caravajal 示例为基础(这对我来说更容易用于异步/等待),我在下面制作了这个稍作修改的版本,用于发布查询,并发送了参数。我添加了throw new Error 语句,因为我无法捕捉到response.ok == false 上的故障。

/**
 *  Generic fetch function
 */
function fetchData(url,parameters,callback) 

  fetch(url,
      method: "POST",
      headers:  "Content-Type": "application/json" ,
      body: JSON.stringify(parameters),
  )
  .then(async(response) => 
      // status 404 or 500 will set ok to false
      if (response.ok) 
          // Success: convert data received & run callback
          result = await response.json();
          callback(result);
      
      else 
          throw new Error(response.status + " Failed Fetch ");
      
  ).catch(e => console.error('EXCEPTION: ', e))

【讨论】:

【参考方案5】:

正如其他人所说, fetch 仅在出现适当的网络问题时才返回错误。 “down”服务器不会返回 4XX,它不会返回任何内容或 5XX,具体取决于它是如何“down”的。 我倾向于使用 axios 而不是 fetch 主要是因为这个问题让我编写了更多代码。

【讨论】:

以上是关于fetch 即使 404 也能解决?的主要内容,如果未能解决你的问题,请参考以下文章

使用 fetch 时拒绝承诺 [重复]

我Nginx服务器设置了404,也能跳转到404但是返回状态码是200?

虚拟主机服务器错误404解决方法

树莓派-ubuntu更换源报 E: Failed to fetch。。。。错误的解决办法

iis特殊后缀文件下载404

PHP文件通过FTP上传,报错“HTTP404",怎么解决?