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

我最近一直在摆弄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 < / p >

但是,如果写成:

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,你可以访问标题属性。 http://jsbin.com/wofulo/edit?js,output < / p >

所以我的问题是:为什么response.json在对象字面量中返回承诺,而在刚刚返回时返回值?

162814 次浏览

这种差异是由于promise的行为而不是fetch()具体造成的。

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

第二段也可以写成:

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

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


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

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

在这种情况下,post只是你创建的Object,它的data属性中包含一个Promise。对实现这一承诺的等待仍未完成。

为什么response.json返回一个承诺?

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

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

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

你可以使用

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

或任何其他访问先前承诺的方法会导致.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
}

另外,帮助我理解你描述的这个特定场景的是Promise API 文档,特别是它解释了then方法返回的Promise将如何根据处理程序fn返回的内容进行不同的解析:

如果处理器函数:

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

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

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

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

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

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

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