185 votes

Pourquoi .json () renvoie-t-il une promesse?

J'ai été déconner avec le fetch() de l'api récemment, et a remarqué quelque chose qui était un peu bizarre.

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.les données renvoie une promesse d'objet. http://jsbin.com/wofulo/2/edit?js,sortie

Cependant, si il est écrit que:

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

let iterator = fetch(url);

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

poste ici, c'est un standard de l'objet auquel vous pouvez accéder à l'attribut title. http://jsbin.com/wofulo/edit?js,sortie

Donc ma question est: pourquoi n'a de réponse.json retour d'une promesse dans un objet littéral, mais le retour de la valeur si juste de rentrer?

229voto

Bergi Points 104242

Pourquoi est - response.json de retour d'une promesse?

Parce que vous recevez de l' response lorsque tous les en-têtes sont arrivées. Appelant .json() vous obtient une promesse pour le corps de la réponse http qui n'est pas encore chargé. Voir aussi Pourquoi l'objet de la réponse à partir de JavaScript chercher de l'API une promesse?.

Pourquoi dois-je obtenir la valeur si je retourne la promesse de l' then gestionnaire?

Parce que c'est la façon dont les promesses de travail. La possibilité de retourner les promesses de la fonction de rappel et son adoption est de leurs caractéristiques les plus pertinentes, il rend chainable sans imbrication.

Vous pouvez utiliser

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

ou de toutes autres approches pour accéder précédente promettent des résultats dans un .alors() de la chaîne pour obtenir le statut de la réponse après avoir attendu le json corps.

24voto

Jonathan Lonowski Points 45253

Cette différence est due au comportement des Promesses de plus de fetch() précisément.

Lorsqu'un .then() callback retourne supplémentaires Promise, du prochain .then() rappel de la chaîne est essentiellement lié à la Promesse, de la réception de sa volonté ou de refuser l'accomplissement et de la valeur.

Le 2ème extrait pourrait également avoir été écrite comme:

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

Dans ce formulaire et le vôtre, la valeur de post est fourni par la Promesse retourné à partir de response.json().


Lorsque vous retournez une plaine Object, même si, .then() estime qu'un bon résultat et se résout immédiatement, similaires à:

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

post dans ce cas est simplement l' Object vous avez créé, qui est titulaire d'un Promise ses data de la propriété. Le temps d'attente pour que la promesse soit accomplie est encore incomplète.

7voto

Gera Zenobi Points 31

Aussi, ce qui m'a aidé à comprendre ce scénario particulier que vous avez décrit, c'est la Promesse de l'API de la documentation, en particulier lorsqu'il explique comment les promis retourné par l' then méthode sera résolu différemment selon que le gestionnaire fn retourne:

si la fonction de gestionnaire:

  • renvoie une valeur, la promesse retourné par alors est résolu avec la valeur retournée de sa valeur;
  • renvoie une erreur, la promesse retourné par puis est rejeté avec l'jetés erreur de sa valeur;
  • retourne un déjà résolu promesse, la promesse retourné par alors est résolu avec la promesse de la valeur de sa valeur;
  • retourne un déjà rejeté la promesse, la promesse retourné par puis est rejeté avec la promesse de la valeur de sa valeur.
  • renvoie une autre dans l'attente de la promesse de l'objet, de la résolution ou de rejet de la promesse retourné par alors être postérieure à la la résolution/le rejet de la promesse retourné par le gestionnaire. Aussi, l' la valeur de la promesse retourné par-là sera la même que la valeur de la promesse retourné par le gestionnaire.

6voto

jcroll Points 2576

En plus des réponses ci-dessus, voici comment vous pouvez gérer une réponse de la série 500 à partir de votre API, où vous recevez un message d'erreur codé 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
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X