为什么 .json() return 是一个承诺?
Why does .json() return a promise?
我最近一直在摆弄 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
return 是一个 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
return 是对象字面量中的承诺,但 return 只是 returned 的值?
这种差异是由于 Promises 的行为比 fetch()
更具体。
当一个 .then()
回调 return 是一个额外的 Promise
时,链中的下一个 .then()
回调基本上绑定到该 Promise,接收它的 resolve 或 reject成就感和价值。
第二个片段也可以写成:
iterator.then(response =>
response.json().then(post => document.write(post.title))
);
在这个表单和你的表单中,post
的值由 return 由 response.json()
编辑的 Promise 提供。
当你 return 一个普通的 Object
时,.then()
认为这是一个成功的结果并立即自行解决,类似于:
iterator.then(response =>
Promise.resolve({
data: response.json(),
status: response.status
})
.then(post => document.write(post.data))
);
post
在这种情况下只是您创建的 Object
,它在其 data
属性 中包含一个 Promise
。等待兑现的承诺还未完成。
Why does response.json
return a promise?
因为您会在 headers 全部到达后立即收到 response
。调用 .json()
会给你另一个尚未加载的 http 响应的 body 的承诺。另见 Why is the response object from JavaScript fetch API a promise?.
Why do I get the value if I return the promise from the then
handler?
因为that's how promises work。 return 从回调中承诺并让它们被采用的能力是它们最相关的特性,它使它们无需嵌套即可链接。
您可以使用
fetch(url).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.status, res.data.title)
}));
或任何其他 approaches to access previous promise results in a .then() chain 在等待 json body.
后获取响应状态
除了上述答案之外,这里还介绍了如何处理来自 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 documentation 帮助我理解了您描述的这个特定场景,特别是它解释了 then
方法返回的 promised 将如何被解析取决于 处理程序 fn returns:
if the handler function:
- returns a value, the promise returned by then gets resolved with the returned value as its value;
- throws an error, the promise returned by then gets rejected with the thrown error as its value;
- returns an already resolved promise, the promise returned by then gets resolved with that promise's value as its value;
- returns an already rejected promise, the promise returned by then gets rejected with that promise's value as its value.
- returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the
resolution/rejection of the promise returned by the handler. Also, the
value of the promise returned by then will be the same as the value of
the promise returned by the handler.
也可以将 await 与 responce.json() 一起使用
const responce = await fetch(url);
const result = await responce.json();
也可以将 await 与 responce.json() 一起使用
json() 方法可用于所有 fetch() 函数。 json() 方法 return 是一个 Promise。请记住,当 returning 一个 Promise 时,它仍然是 pending 因为它是异步的(假设数据还没有)。所以要使用 json() 方法获取数据 AFTER ,你需要使用另一个 then() 方法,因此它只会 return 数据到达后。
回答你的问题,就是这样,这就是这样做的方式。
就像 Promise ---> 另一个 Promise ----> 数据
我最近一直在摆弄 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
return 是一个 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
return 是对象字面量中的承诺,但 return 只是 returned 的值?
这种差异是由于 Promises 的行为比 fetch()
更具体。
当一个 .then()
回调 return 是一个额外的 Promise
时,链中的下一个 .then()
回调基本上绑定到该 Promise,接收它的 resolve 或 reject成就感和价值。
第二个片段也可以写成:
iterator.then(response =>
response.json().then(post => document.write(post.title))
);
在这个表单和你的表单中,post
的值由 return 由 response.json()
编辑的 Promise 提供。
当你 return 一个普通的 Object
时,.then()
认为这是一个成功的结果并立即自行解决,类似于:
iterator.then(response =>
Promise.resolve({
data: response.json(),
status: response.status
})
.then(post => document.write(post.data))
);
post
在这种情况下只是您创建的 Object
,它在其 data
属性 中包含一个 Promise
。等待兑现的承诺还未完成。
Why does
response.json
return a promise?
因为您会在 headers 全部到达后立即收到 response
。调用 .json()
会给你另一个尚未加载的 http 响应的 body 的承诺。另见 Why is the response object from JavaScript fetch API a promise?.
Why do I get the value if I return the promise from the
then
handler?
因为that's how promises work。 return 从回调中承诺并让它们被采用的能力是它们最相关的特性,它使它们无需嵌套即可链接。
您可以使用
fetch(url).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.status, res.data.title)
}));
或任何其他 approaches to access previous promise results in a .then() chain 在等待 json body.
后获取响应状态除了上述答案之外,这里还介绍了如何处理来自 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 documentation 帮助我理解了您描述的这个特定场景,特别是它解释了 then
方法返回的 promised 将如何被解析取决于 处理程序 fn returns:
if the handler function:
- returns a value, the promise returned by then gets resolved with the returned value as its value;
- throws an error, the promise returned by then gets rejected with the thrown error as its value;
- returns an already resolved promise, the promise returned by then gets resolved with that promise's value as its value;
- returns an already rejected promise, the promise returned by then gets rejected with that promise's value as its value.
- returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. Also, the value of the promise returned by then will be the same as the value of the promise returned by the handler.
也可以将 await 与 responce.json() 一起使用
const responce = await fetch(url);
const result = await responce.json();
也可以将 await 与 responce.json() 一起使用
json() 方法可用于所有 fetch() 函数。 json() 方法 return 是一个 Promise。请记住,当 returning 一个 Promise 时,它仍然是 pending 因为它是异步的(假设数据还没有)。所以要使用 json() 方法获取数据 AFTER ,你需要使用另一个 then() 方法,因此它只会 return 数据到达后。
回答你的问题,就是这样,这就是这样做的方式。
就像 Promise ---> 另一个 Promise ----> 数据