1
votes

Ordre d'exécution de la méthode de service angulaire

Je suis nouveau dans Angular et j'essaie maintenant de l'apprendre et j'ai un problème. J'ai une méthode de service simple que j'appelle dans un autre composant. Mais j'ai un ordre d'exécution étrange:

 entrez la description de l'image ici

Vous pouvez le voir dans le navigateur de la console:

 entrez la description de l'image ici

Quelqu'un pourrait-il expliquer comment cela fonctionne? Et comment y remédier?


1 commentaires

L'ordre d'exécution est correct en fonction du code. Ce qui se passe, c'est que la première ligne démarre une requête http qui s'exécute de manière asynchrone à partir du reste du code. Une fois la demande lancée, le reste du code s'exécute. Ce que vous devriez probablement faire, c'est renvoyer votre ligne this.http.get (..) et chaque fois que vous appelez votre fonction, abonnez-vous à la réponse.


3 Réponses :


1
votes

Le code en dehors de la méthode subscribe () est toujours exécuté en dernier. Peu importe si c'est avant ou après si c'est au même niveau.

Pour le réparer au lieu de faire une méthode "get", utilisez une variable globale et initialisez-la sur ngOnInit ().

weather :WeatherForecast = null;

ngOnInit(){
  this.http.get<WeatherForecast>(this._url).subscribe(
    data => {
       this.weather = data;
    }
  )
}

Je vous propose d'organiser des appels http entre component.ts et un service pour le rendre plus indépendant.

J'espère que cela vous aidera :)


2 commentaires

Merci, mais dans tous les cas, si j'ai besoin d'obtenir des données de l'appel http, je dois attendre?


J'ai changé comme vous l'avez dit, mais si un autre code s'exécute après la fonction d'abonnement, comment puis-je obtenir des données à partir d'un appel http? Même si je déménage souscrire à ngOnInit, le résultat sera le même



1
votes

Cela a à voir avec le fait que les opérations d'E / S sont généralement conçues pour être non bloquantes. Mettre en place une requête via http.get est une opération non bloquante. Cela prend du temps et en attendant, votre autre code s'exécutera en premier.

Vous ne voudriez pas que votre application se fige pendant qu'elle attend une réponse de 5 secondes du serveur, n'est-ce pas?

Si vous aimerais afficher votre résultat, vous pouvez simplement diviser votre logique pour cela, comme ceci:

<div>{{ weatherForecast?.summary }}</div>

De cette façon, vous pouvez récupérer vos données indépendamment de leur affichage. Angular détecte le changement de votre variable et rend le résultat. Dans votre modèle, vous feriez simplement:

getWeatherForecast() {
    if(this._weatherForecast) {
        return this._weatherForecast.summary;
    }
}

Cela présente l'avantage que vous ne récupérerez pas de nouvelles données sur le serveur, chaque fois que vous souhaitez afficher votre weatherForecast . Cela vous donne plus de contrôle sur la fréquence et le moment de demander à votre serveur de nouvelles données.

Modifier:

Comme indiqué dans les commentaires, le code se cassera, en essayant d'accéder à une propriété (dans ce cas summary ) sur _weatherForecast . Si vous souhaitez éviter cela, vous avez deux options:

  1. Remplacez votre modèle par:
<div>{{ getWeatherForecast()?.summary }}</div>
  1. Modifiez la logique de votre composant en:
<div>{{getWeatherForecast()}}</div>

Vous pouvez également changer la méthode getWeatherForecast () en get weatherForecast () . De cette façon, vous pouvez y accéder dans votre modèle comme une propriété de votre composant, comme ceci:

_weatherForecast: WeatherForecast = null;

calculateWeatherForecast() {
  this.http.get<WeatherForecast>(this._url).subscribe((data) => {
      this._weatherForecast = data;
  });
}

getWeatherForecast() {
    return this._weatherForecast;
}

J'espère que cela vous aidera!


5 commentaires

Hm ... intéressant. Merci! Mais que se passe-t-il si je dois faire smth avec réponse ou si j'ai une certaine logique? J'ai toujours besoin de l'exécuter dans la méthode d'abonnement?


En général, oui. Le rappel, que vous avez fourni à votre méthode subscribe est simplement là pour vous "dire" quand votre appel asynchrone est terminé et vous donne la possibilité de faire quelque chose avec les données résultantes. Avec un appel de synchronisation, vous le feriez de manière assez similaire. Attendez que les données arrivent, puis changez-les, stockez-les, affichez-les, etc ... Ici, c'est juste un peu différent à ce sujet. Vous ne pouvez pas appliquer de logique à des données qui n'y sont pas encore. Dans Angular, vous souhaitez également «externaliser» votre code qui contient et gère les données vers un Service .


Si ce code fonctionnera? Je ne pense pas. getWeatherForecast renverra undefined


Il renverra null , mais seulement dans la première itération. Une fois qu'Angular a détecté le changement de _weatherForecast , il appellera à nouveau getWeatherForecast () , qui retournera ensuite une valeur.


mais toujours dans la console du navigateur à la première fois seront des erreurs. Est-ce bien? Comment l'éviter?



1
votes

Votre code comporte deux parties:

<₹Synchrone

La partie en dehors de votre méthode d'abonnement est synchrone, c'est-à-dire qu'elle s'exécutera instantanément en suivant le flux d'exécution de votre programme.

<₹Asynchrone

La partie de votre méthode d'abonnement est asynchrone, c'est-à-dire qu'elle ne s'exécutera que lorsque la demande d'obtention sera terminée (la réponse est renvoyée).

<↑Explication

Maintenant que la requête http au serveur prendra un certain temps. donc la partie synchrouns continuera son exécution et elle n'attendra pas la fin de la requête get. donc console.log [1] s’exécutera en premier.

La ligne

renvoie this.weatherForcast

est ensuite exécuté en raison d'un code synchrone et renvoie undefined ce qui provoque une erreur dans la console [2]

Votre fonction subscribe est ensuite appelée ultérieurement (lorsque la demande d'obtention est terminée) et les données sont affichées dans la console [3].

J'espère que ça aide :) Faites-moi savoir si vous avez besoin de plus d'explications :)


0 commentaires