web-dev-qa-db-fra.com

Pourquoi est-ce que j'obtiens une erreur «Impossible d'accéder à la« variable »avant l'initialisation» d'un abonné se référençant lui-même?

Dans mon Angular 8 j'ai un composant qui s'abonne à un service et attend une notification que le service a chargé comme ceci:

constructor(public contentService: ContractService) {
    let self = this;
    let sub = contentService.loaded.subscribe(function(loaded) {
        if (loaded) {
            self.loading = false;
            if (sub) {
                sub.unsubscribe();
            }
        }
    });
}

Cela fonctionne correctement dans la plupart des cas, mais parfois je vois le message d'erreur suivant:

ERROR ReferenceError: Cannot access 'sub' before initialization
    at SafeSubscriber._next (abstract-content.component.ts:51)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:185)
    at SafeSubscriber.next (Subscriber.js:124)
    at Subscriber._next (Subscriber.js:72)
    at Subscriber.next (Subscriber.js:49)
    at BehaviorSubject._subscribe (BehaviorSubject.js:14)
    at BehaviorSubject._trySubscribe (Observable.js:42)
    at BehaviorSubject._trySubscribe (Subject.js:81)
    at BehaviorSubject.subscribe (Observable.js:28)
    at Observable._subscribe (Observable.js:76)

Comme vous pouvez le comprendre à partir du nom, abstract-content-component Est une classe parent qui a plusieurs implémentations donc elle est appelée à partir d'une classe enfant, mais c'est en fait un Shell vide sans logique propre que j'utilise pour créer il est facile de changer de modèle.

Le message d'erreur me semble insensé (la ligne 51 dans ce cas est la vérification de if(sub) que j'ai ajoutée parce que je voyais la même erreur dans la ligne après) car comment l'abonnement peut-il exister si nous sommes à l'intérieur de son propre gestionnaire d'événements? J'utilise ce modèle avec succès ailleurs, pourquoi y a-t-il un problème ici?

2
glenatron

Je suis juste tombé sur le même problème en réalisant que mon code était ancien et écrit alors que je n'en savais pas autant sur rxjs, jet. Je le vois maintenant comme un contre-modèle pour écrire du code de cette façon.

Ce que vous voulez, c'est de n'émettre qu'une seule valeur et de le faire. Plusieurs options

  1. Ce que je fais:

    contentService.loaded .pipe (first (),) .subscribe (...);

  2. OU, tout aussi bien:

    contentService.loaded .pipe (take (1),) .subscribe (...);

  3. utilisez les promesses, elles ne sont pas obsolètes et si vous avez juste besoin de toujours exactement UNE valeur, alors il n'y a vraiment pas de cas d'utilisation pour un "observable" (ou utiliseriez-vous toujours un nombre et en feriez-vous une chaîne lorsque vous en aurez besoin). juste parce que les chiffres sont une chose incroyable;)

Prends soin de toi!

0
hogan