J'ai une fonction qui émet des valeurs en continu.
Ce que je veux ??
Si la condition Math.sign est remplie, je redirige l'utilisateur vers un autre écran et affiche un message toast.
Mais pour le moment, le message toast est affiché en continu, car l'intervalle est continu.
Ce que j'ai essayé?
this.subscription.unsubscribe ()
dans la condition if (Math.sign)
, mais cela n'a pas fonctionné.
Toutes les suggestions sur la façon d'arrêter l'intervalle le code suivant ??
startTimer(validUntil: string) { this.counter$ = interval(1000).pipe( map((x) => { this.diff = Math.floor((new Date(validUntil).getTime() - new Date().getTime()) / 1000); if (Math.sign(this.diff) == -1) { //Tried this.subscription.unsubscribe() here // Redirects me to another component this.goBack(true); } return x; })); this.subscription = this.counter$ .subscribe((x) => { this.message$ = this.dhms(this.diff); }); } goBack(requestExpired: boolean) { if (requestExpired == true) { this.messageDialogService.presentToast('Expired') } this.router.navigate(['mypage']); }
5 Réponses :
Avez-vous essayé de vous désinscrire dans la méthode ngOnDestroy
?
pouvez-vous essayer ça? après la redirection, votre composant sera détruit et vous pourrez donc vous désinscrire dans cet événement du cycle de vie
Je viens d'essayer et ça ne marche pas non plus: | Je continue à porter des toasts en continu
l'interface OnDestroy est-elle implémentée?, voici le brouillon que j'ai fait avec un console.log stackblitz.com/edit/angular-hmmavu?file=src/app/...
La combinaison de ngOnDestroy et de validUntil (par Vahid) a aidé. Merci
À mon avis, takeWhile
avec la condition à l'intérieur est l'approche la plus évidente.
Par exemple:
<div>{ messages$ | async }</div>
REMARQUE : Pourtant, je doute que vous ayez besoin du counter $
. Vous ne pouvez utiliser que le flux message $
avec un tube asynchrone, par exemple
controller
startTimer(validUntil) { this.messages$ = interval(1000).pipe( // ... ) }
template
startTimer(validUntil) { this.counter$ = interval(1000).pipe( // turn value emissions into diffs map(() => Math.floor((new Date(validUntil).getTime() - new Date().getTime()) / 1000)), // this is needed to terminate when condition is met takeWhile(diff => Math.sign(diff) !== -1), // when terminated on conditions -- navigate back finalize(()=>{ this.goBack(true); }) // just in case if user navigates out before condition is met takeUntil(this.destroy$) ) .subscribe(diff => { this.message$ = this.dhms(diff); }); }
J'espère que cela vous aidera
Je pense que le meilleur moyen est d'utiliser takeUntil
pipe.
Regardez cet exemple .
J'ai réécrit votre code en utilisant le tube takeUntil
et filter
. Et j'ai déplacé la fonction goBack
vers le rappel complete
de la fonction d'abonnement.
startTimer(validUntil: string) { this.counter$ = interval(1000); const takeUntil$ = this.counter$.pipe( filter(x => { this.diff = Math.floor((new Date(validUntil).getTime() - Date.now()) / 1000); return Math.sign(this.diff) === -1; }) ); this.counter$.pipe(takeUntil(takeUntil$)).subscribe( x => { this.message$ = this.dhms(this.diff); }, undefined, () => { this.goBack(true); } ); }
Toujours le même toast continu
@MariumMalik Veuillez enregistrer Math.sign (this.diff) === -1
dans le tube filter
pour voir si cela devient vrai.
Oui, après quelques valeurs, c'est -1 et devient vrai
@MariumMalik Donc, la méthode this.goBack
devrait être appelée. Si elle est appelée et que vous recevez toujours des messages toast, alors il y a un problème avec cette ligne: this.message $ = this.dhms (this.diff);
. Je n'ai aucune idée de ce que fait cette ligne.
Oui, la fonction est appelée et je suis renvoyé vers un autre composant avec des toasts continus
this.dhms renvoie juste une valeur au format heure et est utilisé dans mon composant (donc il n'a pas de lien)
@MariumMali. Je ne sais pas comment fonctionne this.message $
mais peut-être si vous mettez this.message $ .unsubscribe ()
avant this.goBack
Ça marche.
La combinaison de ngOnDestroy (suggéré par une autre personne) et de validUntil a aidé. Merci
Autant que je sache, la fonction intervalle
cesse d'émettre après la désinscription, j'ai également créé un exemple stackblitz pour le démontrer.
Pour une raison quelconque, votre code n'appelle pas la méthode unsubscribe
, et je vous conseille de rechercher le problème ici, peut-être en ajoutant un débogueur avant d'appeler unsubscribe code > pour vérifier s'il est réellement exécuté.
Vérifiez également que vous appelez unsubscribe
sur le bon objet, il doit s'agir de subscription et non de timer $ , par exemple.
Mais je pense qu'il n'y a aucun doute que le problème vient du code que vous avez montré.
En fait, il semble que vous ayez besoin de régler un minuteur pour une durée donnée, essayez
startTimer(validUntil) { // duration in seconds till invalid const duration = Math.floor((new Date(validUntil).getTime() - Date.now()) / 1000)); this.messages$ = timer(0, 1000).pipe( // we take 1 more emission to encompass starting emission take(duration + 1) // once given number of seconds passed -- navigate back finalize(()=>{ this.goBack(true); }) // just in case if user navigates out before condition is met // this is needed if you wont use |async pipe takeUntil(this.destroy$) // map to display time map(value => this.dhms(duration - value)) ); }
où N
est la différence en secondes entre l'heure actuelle et validUntil
. Donc
timer(0, 1000).pipe( take(N) )
Et puis appliquer | async
conduit au message $
dans le modèle.
J'espère que cela vous aidera
Où appelez-vous
this.subscription.unsubscribe ()
?@martin Dans ma condition if (Math.sign)
Donc ça n'a probablement jamais été appelé
La fonction après cette ligne est appelée et je suis redirigé vers un autre écran. Donc, cette ligne est au-dessus et elle doit avoir été appelée ...