web-dev-qa-db-fra.com

Le service Angular2 Observable BehaviorSubject ne fonctionne pas

J'essaie de créer mon propre service observable mais après avoir obtenu les données initiales du service, les mises à jour du service ne sont propagées à aucun abonné. Le service ressemble à ceci:

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs/Rx';

@Injectable()
export class DataService {
  keys : number[] = [4,5,1,3,2];
  private data :BehaviorSubject<number[]> = new BehaviorSubject(this.keys);

  constructor() {};

  public setKey(i:number, val:number) :void {
    this.keys[i]=val;
    this.data.next(this.keys);
  }
  public getData() :Observable<number[]> {
    return new Observable(fn => this.data.subscribe(fn));
  }
  public getKeys() :number[] {
    return this.keys;
  }
}

le composant utilisant le service obtient très bien les données initiales. ce composant obtient ses données dans le constructeur:

constructor(public dataService: DataService) {
    dataService.getData().subscribe(data => {
      console.log("Gotcha!");
      this.data.datasets[0].data = data)
    });
};

ce qui donne un Gotcha dans le journal de la console. Mais après avoir mis à jour les données avec setKey (2,3) ailleurs, je m'attendais à this.data.next (this.keys); d'envoyer des données à tous les abonnés et les données seraient mises à jour dans ce composant en conséquence. mais aucune donnée n'est envoyée aux abonnés ..

je pensais avoir compris les observables mais s'il vous plaît ne soyez pas amical si je manque le point ici;) tous les pointeurs dans la bonne direction seront grandement appréciés!

17
kjoetools

Chaque fois que vous émettez une valeur, vous devez créer un nouvel objet au lieu d'émettre le même objet muté. Cela vous protégera des problèmes de détection des modifications. Il serait préférable de toujours assigner un nouvel objet à this.keys Lorsque vous le changez.

this.data.next([...this.keys]);

Vous pouvez utiliser asObservable() ici

public getData(): Observable<number[]> {
  return this.data.asObservable();
}

Vérifiez également ce que Günter Zöchbauer a dit. Offrez-vous le service en tant que singleton?

9
j2L4e

J'ai rencontré le même problème à un moment donné. La raison en est probablement que votre service n'est pas un singleton, c'est-à-dire que chaque abonné obtient une nouvelle instance. Contrairement à Angular 1, dans les services A2 ne sont pas des singletons.

Si vous souhaitez partager une instance du service entre plusieurs services/composants, placez-la dans providers de votre parent @Component ou @NgModule.

@NgModule({
  declarations: [],
  imports: [],
  bootstrap: [AppComponent],
  providers: [DataService]
})
export class AppModule {
}
35
Konrad Garus