Fetch 拒绝对 404 响应的承诺,而不是使用 404 状态解析

Fetch rejects promise on 404 responses instead of resolving with 404 status

我正在尝试弄清楚如何在 reason-react-example 存储库的获取示例中处理失败的 http 响应。

以下是我的第一个想法(修补url):

Js.Promise.(
          Fetch.fetch("https://dog.ceo/api/breeds/list")
          |> then_(res => {
               let ok = Fetch.Response.ok(res);
               ok ?
                 Fetch.Response.json(res) :
                 Js.Exn.raiseError(Fetch.Response.statusText(res));
             })
          |> then_(json =>
               json
               |> Decode.dogs
               |> (dogs => self.send(DogsFetched(dogs)))
               |> resolve
             )
          |> catch(err => {
               Js.log(err);
               [%bs.raw {| console.log(err.response) |}]
               Js.Promise.resolve(self.send(DogsFailedToFetch));
             })
          |> ignore
        );

它没有像我希望的那样工作。事实证明,当 HTTP 请求失败并显示 404 时,Fetch 会立即拒绝,这是我没想到的,因为这不是浏览器获取 API 的工作方式。此外,当记录 err 时,它是 TypeError: Failed to fetch 并且 err.response 属性 未定义。

我的问题是:如何处理错误以获取状态代码和状态文本?

问题是 CORS。您使用的服务器将包含 Access-Control-Allow-Origin: * header 和 2xx 响应,但不包含 404 响应。所以显然你只能从这个服务器读取成功的响应。

您应该会在控制台中收到一些额外的警告或错误,告诉您类似以下内容:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://dog.ceo/api/breeds/listio. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

[Error] Origin null is not allowed by Access-Control-Allow-Origin.

[Error] Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin. (listio, line 0)

[Error] Fetch API cannot load https://dog.ceo/api/breeds/listio. Origin null is not allowed by Access-Control-Allow-Origin.

您可以通过使用 no-cors 模式来解决这个问题,至少在测试时是这样。使用 bs-fetch 你会做:

Fetch.fetchWithInit(url, Fetch.RequestInit.make(~mode=Fetch.NoCORS, ()))