为什么.json()会返回一个承诺?

时间:2016-05-31 20:26:07

标签: javascript asynchronous promise fetch-api

我最近一直在讨论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));
;

post.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这里是标准Object,您可以访问title属性。 http://jsbin.com/wofulo/edit?js,output

所以我的问题是:为什么response.json会在对象文字中返回一个promise,但是如果刚刚返回则返回值?

6 个答案:

答案 0 :(得分:115)

  

为什么response.json会返回承诺?

因为当所有标头到达时您收到response。调用.json()可以获得尚未加载的http响应正文的承诺。另请参阅Why is the response object from JavaScript fetch API a promise?

  

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

因为that's how promises work。从回调中返回promises并获取它们的能力是它们最相关的特性,它使它们可以链接而不需要嵌套。

您可以使用

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

或任何其他approaches to access previous promise results in a .then() chain获取响应状态。

答案 1 :(得分:12)

这种差异是由于Promises的行为特别是fetch()

.then()回调返回额外的Promise时,链中的下一个.then()回调基本上绑定到该Promise,接收其解析或拒绝履行和值。

第二个片段也可以写成:

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

在此表单和您的表单中,post的值由response.json()返回的承诺提供。

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

iterator.then(response =>
    Promise.resolve({
      data: response.json(),
      status: response.status
    })
    .then(post => document.write(post.data))
);
在这种情况下,

post只是您创建的Object,其Promise属性中包含data。等待履行承诺的工作仍然不完整。

答案 2 :(得分:7)

另外,有什么帮助我理解你描述的这个特定场景是Promise API documentation,特别是它解释了then方法返回的承诺将如何以不同的方式解决,具体取决于< strong> handler fn 返回:

  

如果处理函数:

     
      
  • 返回一个值,然后返回的promise将以返回值作为其值进行解析;
  •   
  • 抛出错误,然后返回的promise将被抛出错误作为其值被拒绝;
  •   
  • 返回已经解决的承诺,然后返回的承诺将以该承诺的值作为其值来解决;
  •   
  • 返回已被拒绝的承诺,然后返回的承诺将被拒绝,并将该承诺的值作为其值。
  •   
  • 返回另一个待处理的promise对象,然后返回的promise的解析/拒绝将在   解析/拒绝处理程序返回的承诺。而且,   当时返回的promise的值将与value的值相同   处理程序返回的承诺。
  •   

答案 3 :(得分:5)

除了上面的答案之外,这里是你如何处理来自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
}

答案 4 :(得分:-1)

我刚刚找到的另一个选项是:

  1. const response = fetch("url")
  2. const data = await response.json()
  3. 常量信息 = 等待数据

信息”是最终回复:)

答案 5 :(得分:-1)

也将 await 与 responce.json() 一起使用

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

也将 await 与 responce.json() 一起使用