javascript - fetching - ¿Por qué.json() devuelve una promesa?
javascript fetch syntax (4)
¿Por qué
response.json
devuelve una promesa?
Porque recibes la
response
tan pronto como llegan todos los encabezados.
Llamar a
.json()
da otra promesa para el cuerpo de la respuesta http que aún no se ha cargado.
Consulte también
¿Por qué el objeto de respuesta de JavaScript fetch API es una promesa?
.
¿Por qué obtengo el valor si devuelvo la promesa del
then
controlador?
Porque así es como funcionan las promesas . La capacidad de devolver promesas de la devolución de llamada y lograr que se adopten es su característica más relevante, las hace encadenables sin anidar.
Puedes usar
fetch(url).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.status, res.data.title)
}));
o cualquier otro de los enfoques para acceder a resultados de promesas anteriores en una cadena .then () para obtener el estado de respuesta después de haber esperado el cuerpo de json.
He estado jugando con la API
fetch()
recientemente, y noté algo que era un poco peculiar.
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
devuelve un objeto
Promise
.
http://jsbin.com/wofulo/2/edit?js,output
Sin embargo, si está escrito como:
let url = "http://jsonplaceholder.typicode.com/posts/6";
let iterator = fetch(url);
iterator
.then(response => response.json())
.then(post => document.write(post.title));
;
post
aquí es un
Object
estándar al que puede acceder el atributo de título.
http://jsbin.com/wofulo/edit?js,output
Entonces mi pregunta es: ¿por qué
response.json
devuelve una promesa en un objeto literal, pero devuelve el valor si solo se devuelve?
Además de las respuestas anteriores, aquí es cómo puede manejar una respuesta de la serie 500 desde su API donde recibe un mensaje de error codificado en 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
}
Además, lo que me ayudó a comprender este escenario particular que describió es la
documentation
Promise API, específicamente donde explica cómo lo prometido devuelto por el método de
then
se resolverá de manera diferente dependiendo de lo que devuelva el
controlador fn
:
si la función del controlador:
- devuelve un valor, la promesa devuelta para entonces se resuelve con el valor devuelto como su valor;
- arroja un error, la promesa devuelta para entonces es rechazada con el error arrojado como su valor;
- devuelve una promesa ya resuelta, la promesa devuelta para entonces se resuelve con el valor de esa promesa como su valor;
- devuelve una promesa ya rechazada, la promesa devuelta para entonces se rechaza con el valor de esa promesa como su valor.
- devuelve otro objeto de promesa pendiente, la resolución / rechazo de la promesa devuelta para entonces será posterior a la resolución / rechazo de la promesa devuelta por el controlador. Además, el valor de la promesa devuelta para entonces será el mismo que el valor de la promesa devuelta por el controlador.
Esta diferencia se debe al comportamiento de Promises más que a
fetch()
específicamente.
Cuando una devolución de llamada
.then()
devuelve una
Promise
adicional, la siguiente devolución de llamada
.then()
en la cadena está esencialmente vinculada a esa Promesa, recibiendo su resolución o rechazo de cumplimiento y valor.
El segundo fragmento también podría haberse escrito como:
iterator.then(response =>
response.json().then(post => document.write(post.title))
);
Tanto en este formulario como en el suyo, el valor de la
post
lo proporciona la Promesa devuelta por
response.json()
.
Sin embargo, cuando devuelve un
Object
simple,
.then()
considera que es un resultado exitoso y se resuelve de inmediato, similar a:
iterator.then(response =>
Promise.resolve({
data: response.json(),
status: response.status
})
.then(post => document.write(post.data))
);
post
en este caso es simplemente el
Object
que creó, que contiene una
Promise
en su propiedad de
data
.
La espera de que se cumpla esa promesa aún es incompleta.