我最近一直在摆弄fetch() api,并注意到一些有点奇怪的东西。

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));
;

职位。data返回一个Promise对象。 http://jsbin.com/wofulo/2/edit?js,output

但是,如果写成:

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

let iterator = fetch(url);

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

post是一个标准的对象,你可以访问它的title属性。 http://jsbin.com/wofulo/edit?js,output

所以我的问题是:为什么反应。Json返回一个承诺在一个对象字面量,但返回值如果刚刚返回?


当前回答

也可以在response .json()中使用await

const responce = await fetch(url);
const result = await responce.json();

也可以在response .json()中使用await

其他回答

这种差异主要是由于Promises的行为而不是fetch()。

当.then()回调返回一个额外的Promise时,链中的下一个.then()回调本质上绑定到该Promise,接收它的解决或拒绝实现和值。

第二段也可以写成:

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

在这个表单和你的表单中,post的值都是由response.json()返回的Promise提供的。


然而,当你返回一个普通对象时,.then()认为这是一个成功的结果,并立即解析自己,类似于:

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

在本例中,post只是您创建的对象,它的data属性中包含一个Promise。对实现这一承诺的等待仍未完成。

json()方法可用于所有fetch()函数。json()方法返回一个Promise。请记住,当返回Promise时,它仍然是挂起的,因为它是异步的(假设数据还不存在)。因此,要在使用json()方法之后获取数据,您需要使用另一个then()方法,以便它在到达后返回数据。

回答你的问题,就是这样,就是这样做的方式。

它就像承诺->另一个承诺---->数据

为什么会反应。Json返回承诺?

因为当所有的报头到达时,您就会收到响应。调用.json()会为尚未加载的http响应正文提供另一个承诺。参见为什么从JavaScript获取API的响应对象是一个承诺?。

如果我从当时的处理程序返回承诺,为什么我得到这个值?

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

你可以使用

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正文后获得响应状态。

除了上面的答案,这里还有你如何处理来自api的500系列响应,在那里你会收到一个json编码的错误消息:

function callApi(url) {
  return fetch(url)
    .then(response => {
      if (response.ok) {
        return response.json().then(response => ({ response }));
      }

      return response.json().then(error => ({ error }));
    })
  ;
}

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

const { response, error } = callApi(url);
if (response) {
  // handle json decoded response
} else {
  // handle json decoded 500 series response
}

也可以在response .json()中使用await

const responce = await fetch(url);
const result = await responce.json();

也可以在response .json()中使用await