为什么 .json() 返回一个 promise?

我最近一直在搞砸api,并注意到一些有点古怪的东西。fetch()

let url = "http://jsonplaceholder.typicode.com/posts/6";

let iterator = fetch(url);

iterator
  .then(response => {
      return {
          data: response.json(),
          status: response.status
      }
  })
  .then(post => document.write(post.data));
;

post.data返回一个对象。http://jsbin.com/wofulo/2/edit?js,outputPromise

但是,如果它写成:

let url = "http://jsonplaceholder.typicode.com/posts/6";

let iterator = fetch(url);

iterator
  .then(response => response.json())
  .then(post => document.write(post.title));
;

post这是一个标准,您可以访问标题属性。http://jsbin.com/wofulo/edit?js,outputObject

所以我的问题是:为什么在对象文本中返回一个承诺,但如果只是返回,则返回值?response.json


答案 1

为什么要退货?response.json

因为一旦所有标头都已到达,您就会收到 。调用会为尚未加载的 http 响应的正文提供另一个承诺。另请参阅为什么来自 JavaScript fetch API 的响应对象是一个承诺?response.json()

如果我从处理程序返回 promise,为什么我会得到这个值?then

因为这就是承诺的运作方式。从回调中返回承诺并采用它们的能力是它们最相关的功能,它使它们无需嵌套即可链接。

您可以使用

fetch(url).then(response => 
    response.json().then(data => ({
        data: data,
        status: response.status
    })
).then(res => {
    console.log(res.status, res.data.title)
}));

或任何其他访问先前 promise 的方法都会生成 .then() 链,以便在等待 json 正文后获取响应状态。


答案 2

这种差异是由于 Promise 的行为,而不是具体原因。fetch()

当一个回调返回一个附加的,链中的下一个回调基本上绑定到该承诺,接收其解析或拒绝履行和价值。.then()Promise.then()

第二个片段也可以写成:

iterator.then(response =>
    response.json().then(post => document.write(post.title))
);

在此形式和您的形式中,的值由从 返回的承诺提供。postresponse.json()


但是,当您返回一个普通的 时,会考虑一个成功的结果并立即自行解决,类似于:Object.then()

iterator.then(response =>
    Promise.resolve({
      data: response.json(),
      status: response.status
    })
    .then(post => document.write(post.data))
);

post在这种情况下,只是您创建的,它在其属性中保存了 。等待这一承诺实现的工作仍然不完整。ObjectPromisedata