96 votes

Comportement de la valeur initiale du sujet null ?

private customer: Subject<Object> = new BehaviorSubject<Object>(null);

setCustomer(id, accountClassCode) {
    this.customer.next({'id': id, 'accountClassCode': accountClassCode});
}

getCustomer() {
    return this.customer.asObservable();
}

J'utilise cette partie du code mais j'obtiens une erreur qui ne peut pas trouver l'id de null. Y a-t-il une solution pour obtenir une valeur initiale qui n'est pas nulle ?

1 votes

Avez-vous essayé un objet vide ? new BehaviorSubject<Object>({}) ;

0 votes

Je reçois une erreur Les paramètres fournis ne correspondent à aucune signature de l'appel cible.

2 votes

Il y a une solution. N'utilisez pas BehaviorSubject si vous n'avez pas besoin de la valeur initiale.

184voto

estus Points 5252

Le but de BehaviorSubject est de fournir une valeur initiale. Elle peut être null ou quoi que ce soit d'autre. Si aucune valeur initiale valide ne peut être fournie (lorsque l'identifiant de l'utilisateur n'est pas encore connu), elle ne doit pas être utilisée.

ReplaySubject(1) a un comportement similaire (émet la dernière valeur lors de l'abonnement) mais n'a pas de valeur initiale tant qu'elle n'est pas définie par la commande next .

Il devrait être

private customer: Subject<Object> = new ReplaySubject<Object>(1);

6 votes

La valeur par défaut est 1 si vous ne la spécifiez pas, donc new ReplaySubject<Foo>() est meilleur. La spécification du type ne fait rien au moment de l'exécution, mais fournit une sécurité de type au moment de la compilation.

0 votes

Si vous êtes intéressé, voici le code source : github.com/ReactiveX/rxjs/blob/master/src/internal/

2 votes

Préférez ReplaySubject.create<Object>(1)

21voto

Bellash Points 1330

Puisque l'objet peut être nul, un meilleur choix est de déduire le type comme ceci

 private customer = new BehaviorSubject<Customer|null>(null);

5voto

SrAxi Points 8077

Essayez de structurer votre service de cette manière :

Service :

@Injectable()
export class MyService {
    customerUpdate$: Observable<any>;

    private customerUpdateSubject = new Subject<any>();

    constructor() {
        this.customerUpdate$ = this.customerUpdateSubject.asObservable();
    }

    updatedCustomer(dataAsParams) {
        this.customerUpdateSubject.next(dataAsParams);
    }
}

N'oubliez pas d'ajouter MyService aux fournisseurs.

Lorsque vous mettez à jour votre client (si c'est le cas), vous faites quelque chose comme ceci :

Composant (Celui qui déclenche) :

constructor(private myService: MyService) {
        // I'll put this here, it could go anywhere in the component actually
        // We make things happen, Client has been updated
        // We store client's data in an object
        this.updatedClient = this.myObjectWithUpdatedClientData;  // Obj or whatever you want to pass as a parameter
        this.myService.updatedCustomer(this.updatedClient);
    }

Composant (celui qui est souscrit) :

this.myService.customerUpdate$.subscribe((updatedClientData) => {
            // Wow! I received the updated client's data
            // Do stuff with this data!
        }
    );

D'après ce que j'ai compris, vous essayez de faire passer des données d'un composant à un autre. Vous récupérez les données de votre client et les envoyez à un autre composant via votre application, n'est-ce pas ? C'est pourquoi j'ai posté cette solution.

Si vous êtes intéressé par d'autres types d'abonnements, lisez ceci :

Observables spéciaux d'Angular 2 (Subject / Behaviour subject / ReplaySubject)

1 votes

Hm, j'ai copié-collé la solution exacte et elle ne fonctionne pas pour moi pour une raison quelconque, très étrange.

4voto

Sridhar Chidurala Points 526

Une autre façon est d'utiliser pipe pour filtrer jusqu'à ce qu'une valeur non nulle soit reçue. Cela peut être fait avec takeWhile également.

.pipe(filter(val => !!val)).subscribe(x => {});

2voto

Crow Magnumb Points 901

J'ai trouvé de nombreux cas où je veux la simplicité de ReplaySubject(1) mais veulent aussi le value propriété de BehaviorSubject En d'autres termes, il stocke votre valeur la plus récente pour la récupérer sans avoir à vous abonner. Et en utilisant BehaviorSubject était toujours ennuyeux étant donné la nécessité d'une valeur initiale qui est diffusée, une condition que je souhaitais rarement. À cette fin, j'ai créé mon propre CurrentSubject .

import { ReplaySubject } from "rxjs";

export class CurrentSubject<T> extends ReplaySubject<T> {
    value: T;

    set(value?: T) {
        this.value = value;
        this.next(value);
    }
}

Je voulais remplacer le next mais je n'ai pas réussi à la faire fonctionner pour une raison quelconque, alors j'ai opté pour une méthode appelée set . Ma tentative de contournement ressemblait à ceci...

export class CurrentSubject<T> extends ReplaySubject<T> {
    value: T;

    next(value?: T) {
        this.value = value;
        super.next(value);
    }
}

Je ne sais pas pourquoi la surcharge n'a pas fonctionné.

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