为什么来自 JavaScript fetch API 的响应对象是一个承诺?

Why is the response object from JavaScript fetch API a promise?

当使用 JavaScript 获取 API 从服务器请求时,您必须执行类似

的操作
fetch(API)
  .then(response => response.json())
  .catch(err => console.log(err))

在这里,response.json() 正在兑现它的诺言。

问题是,如果你想捕获 404 的错误,你必须解决响应承诺,然后拒绝获取承诺,因为你只会在 catch 结束,如果出现网络错误。所以 fetch 调用变成了

fetch(API)
  .then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
  .catch(err => console.log(err))

这是更难阅读和推理的东西。所以我的问题是:为什么需要这个?将承诺作为响应值有什么意义?有没有更好的方法来处理这个问题?

如果您的问题是 "why does response.json() return a promise?",那么@Bergi 会在评论中提供线索:"it waits for the body to load"。

如果您的问题是 "why isn't response.json an attribute?",则需要 fetch 延迟返回其响应,直到正文加载完毕,这对某些人来说可能没问题,但不是每个人。

这个 polyfill 应该可以满足您的需求:

var fetchOk = api => fetch(api)
  .then(res => res.ok ? res : res.json().then(err => Promise.reject(err)));

那么你可以这样做:

fetchOk(API)
  .then(response => response.json())
  .catch(err => console.log(err));

反向不能填充。

因为有时我们需要精确控制加载过程(从接收第一条数据到接收最后一条数据)。

在现实世界中,json 可能不是一个很好的例子,因为它相对较小。但是想象一个大图逐渐加载的情况(从马赛克到清晰)。在那种情况下,当数据接收完全完成时通知程序已经太晚了。

因为fetch()是比较低级的api,不然你可以用axios之类的