我正试图弄清楚如何在reason-react-example repo的fetch示例中处理失败的http响应。
以下是我的第一个想法(修补网址):
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
属性未定义。
我的问题是:如何处理错误以获取状态代码和状态文本?
答案 0 :(得分:1)
问题是CORS。您正在使用的服务器将包含Access-Control-Allow-Origin: *
标头,其中包含2xx
个响应,但不会包含404
个响应。显然,您只能从该服务器读取成功的响应。
您应该在控制台中收到一些警告或错误,告诉您类似的内容:
阻止跨源请求:同源策略禁止在https://dog.ceo/api/breeds/listio读取远程资源。 (原因:缺少CORS标题'Access-Control-Allow-Origin'。
或
[错误] Access-Control-Allow-Origin不允许原点为空。
[错误]无法加载资源:Access-Control-Allow-Origin不允许使用Origin null。 (listio,第0行)
[错误] Fetch API无法加载https://dog.ceo/api/breeds/listio。 Access-Control-Allow-Origin不允许使用null。
您可以使用no-cors
模式解决此问题,至少在测试时是这样。使用bs-fetch
,您可以:
Fetch.fetchWithInit(url, Fetch.RequestInit.make(~mode=Fetch.NoCORS, ()))