0

J'ai deux appels de service angulaires dans lesquels l'appel de service 2 doit être effectué sur le résultat d'une valeur du 1er appel de service. Mais mon code n'atteint pas du tout le second appel de service. Veuillez trouver l'extrait de code ci-dessous.Les résultats de l'appel de service Angular2 retournent indéfini, mais peuplent les données

ngOnInit(): void { laissez personId: string = this._activatedRoute.snapshot.params ['id'];

this._personService.getPersonById(personId) 
     .then(person => this.person = person); 

    console.log(this.person); --prints undefined but displays data within the html correctly. 

    if (this.person) { 
    this._teamService.getTeamById(this.person.teamId) 
      .then(teamData => this.team = teamData); 
    } 
} 
+0

Merci pour l'explication, j'ai essayé comme ci-dessous et il les erreurs que « ne peut pas lire la propriété « teamid » undefined » parce que la valeur d'entrée « this.person.teamId » ne sont pas disponibles. this._teamService.getTeamById (this.person.teamId) .then (teamData => {if (this.personnel! == indéfini) {this.team = teamData; }}); –

+0

Je ne suis pas capable de penser à d'autres alternatives qui pourraient éviter le problème de rappel, toute aide serait grandement appréciée. –

+0

Merci. J'ai ajouté "console.log" pour vérifier la valeur this.person.teamId car j'obtiens une erreur sur les outils de développement du navigateur comme "Impossible de lire la propriété 'teamId'". J'ai ajouté attendre comme vous l'avez démontré et il me donne une erreur de compilation comme "Ne trouve pas de nom d'attente" Je suis nouveau à ANgular2, pouvez-vous s'il vous plaît me corriger. Merci –

Répondre

0

Ajoutez un wait à votre _personService.getPersonById puisqu'il renvoie une promesse.

Le fichier console.log ne sera envoyé qu'une fois l'attente précédente terminée.

public async ngOnInit() { 
     await this._personService.getPersonById(personId) 
      .then(person => this.person = person) 
      .catch(err => console.log(err)); 

     console.log(this.person); 

     if (this.person) { 
     await this._teamService.getTeamById(this.person.teamId) 
       .then(teamData => this.team = teamData) 
       .catch(err => { 
        // note curlys allow multiple statments. 
        // do work with error, log it etc.. 
       } 
     }  
    } 

En ce qui concerne la valeur en HTML et non en mode console. La liaison de données HTML affichera le résultat de Promise dès qu'il aura la valeur. Le fichier console.log est appelé immédiatement (quelques ms) après getPersonById et lorsqu'il n'est pas en attente, il n'a pas la valeur à ce moment précis.

Voici comment faire ceci en imbriquant les fonctions. Notez le async person.

public async ngOnInit() { 

    await this._personService.getPersonById(personId) 
     .then(async person => { 
     // To Use await inside .then, add async like above 
     this.person = person; 
     await this._teamService.getTeamById(this.person.teamId) 
      .then(teamData => this.team = teamData) 
      .catch(err => console.log(err)); 
     }) 
     .catch(err => console.log(err)); 

    console.log(this.person); 

Lorsque vous appelez une fonction qui renvoie une promesse, alors sera appelé après la première promesse est résolu .. Et .thens suivantes (vous pouvez les ajouter). Les thens fonctionnent toujours de manière synchrone. Trop de cela s'appelle 'chaînage' et est perçu comme un mauvais design. Thens sont séquentiels/synchrones, peu importe si vous utilisez en attente ou non.

Si vous voulez que les fonctions de l'outter attendent (ou 'bloquent') pour qu'elles s'exécutent également de manière synchrone, vous les attendez également.

Dernière édition: Je suggère d'utiliser le suivant copié d'un autre SO answer pour en savoir plus sur async/await.

utilisant:

public delay(ms: number) { 
    return new Promise(resolve => setTimeout(resolve, ms)); 
} 

Appelez le suivant et notez l'ordre de la sortie .. Ajouter et le changement attend pour apprendre comment il se comporte.

public async someFcn() { 
    console.log('1'); 
    this.delay(2000) 
     .then(x => console.log('2')); 
console.log(3) 
await this.delay(1000) 
    .then(x => console.log('4') 
    .then(x => console.log('5'); 
console.log('Done'); 
} 
+0

Merci. J'ai ajouté "console.log" pour vérifier la valeur this.person.teamId car j'obtiens une erreur sur les outils de développement du navigateur comme "Impossible de lire la propriété 'teamId'". J'ai ajouté attendre comme vous l'avez démontré et il me donne une erreur de compilation comme "Ne trouve pas de nom d'attente" Je suis nouveau à ANgular2, pouvez-vous s'il vous plaît me corriger. Merci –

+0

Vous pouvez activer le mot-clé await en rendant la fonction asynchrone. Vous faites cela en ajoutant le mot-clé 'async' entre public et ngOnInit(). – ttugates

+0

Merci, cela fonctionne maintenant. quelques questions. Mon ngOnit() appelle en fait deux services personne et équipe, le moment où j'ai fait ma fonction async, il voulait que je retourne une valeur au lieu de vide. Je n'étais pas sûr si je devrais retourner/peut retourner les deux mais j'ai essayé avec juste comme ci-dessous et cela fonctionne maintenant. Je ne suis pas sûr que ce soit vraiment correct d'écrire. 'async ngOnInit(): promesse {wait this._personService.getPersonById (personId) .then (personne => this.person = personne); .... return this.person; } ' –

0

Votre appel de service renvoie une Promise, qui est asynchrone - Le reste de votre code ne sera pas bloqué par l'appel à then.

donc vos impressions de la console undefined, la if vérification échoue, et « alors » à un moment futur vos déclarations d'appels de service et votre premier then est exécuté (le second est jamais exécuté à cause de votre if).

Vous pouvez résoudre ce problème en mettant votre déclaration if dans votre then, ou rechercher des techniques pour éviter le «rappel de l'enfer».