2017-08-23 5 views
0

Ceci est mon DataService:angulaire 2 manipulation de données BehaviorSubject dans le composant reflète en service

private resultsChanged$: BehaviorSubject<Test[]> = 
         new BehaviorSubject<any>([]); 

constructor(private http: Http) { } 

public getLatestTrends(): Observable<Test[]> { 
    const latestUrl = `api/tests/trends/groupname=${this.group}&name=${this.team}`; 
    return this.http.get(this.baseUrl + latestUrl) 
     .switchMap((res) => { 
     const json = res.json(); 
     console.log(json); 
     this.resultsChanged$.next(json as Test[]); 
     return json; 
    }); 
} 

public getSubject(): Observable<Test[]> { 
    return this.resultsChanged$.asObservable(); 
} 

C'est le composant qui utilise la DataService et formate les données renvoyées:

private latestTests: Test[]; 
private subscription: Subscription; 

constructor(private testDataService: TestDataService) { } 

ngOnInit() { 

    this.subscription = this.testDataService.getSubject() 
     .subscribe((res) => { 
      if (res === undefined || res.length < 1) { 
       return; 
      } 

      this.latestTests = this.getFormattedTests(res.reverse()); 
     }); 
} 

getFormattedTests(trends) { 
    let formattedTests = []; 

    if (trends === undefined || trends === null) { 
     return formattedTests; 
    } 
    formattedTests = trends.map((trend) => { 

     if (this.isPassed(trend.ran, trend.passed, trend.total)) { 
      trend.state = 'check_circle'; 
      trend.color = 'green'; 
     } else { 
      trend.state = 'warning'; 
      trend.color = 'red'; 
     } 

     const ranPercent = this.getFixedPercent(trend.ran, trend.total); 
     const passPercent = this.getFixedPercent(trend.passed, trend.ran); 
     const failPercent = this.getFixedPercent(trend.failed, trend.ran); 

     trend.notRun = trend.total - trend.ran; 
     trend.ran = `${trend.ran} (${ranPercent})`; 
     trend.passed = `${trend.passed} (${passPercent})`; 
     trend.failed = `${trend.failed} (${failPercent})`; 

     return trend; 
    }); 

return formattedTests; 

}

Le code HTML

<tr *ngFor="let test of latestTests"> 
     <td> 
     <span><md-icon [ngStyle]="getStateOfBuild(test)">{{test.state}}</md-icon> {{test.versionString}}</span> 
     </td> 
     <td>{{test.total}}</td> 
     <td>{{test.ran}}</td> 
     <td>{{test.passed}}</td> 
     <td>{{test.failed}}</td> 
     <td>{{test.notRun}}</td> 
     <td></td> 
     <td>{{test.duration | duration }}</td> 
</tr> 

Bon, alors, quand le site se charge, les données sont formatées et enregistrées dans la variable latestTests. Lorsque je fais un cycle entre mes routes afin que le ngInit soit appelé à nouveau, les données sont reformatées, ce que je ne comprends pas. La chose étrange est que quand je console.log (json); dans le DataService, il déconnecte les données formatées et non l'original ... Comment est-ce possible ?! C'est comme si les données du BehaviorSubject étaient modifiées d'une manière ou d'une autre. Qu'est-ce que je rate?

S'il vous plaît aider et commenter si je dois préciser.

+0

'BehaviorSubject' stocke la dernière valeur qu'il a reçu et rejoue à chaque observateur sur abonnement. – martin

+0

Et c'est ce qu'il est censé faire, mais la dernière valeur semble changer lorsque le composant le formate dans ngOnInit .. Le composant ne devrait pas être capable de manipuler les données des sujets comme ça ?? –

+0

Êtes-vous sûr de ne pas manipuler la même instance du tableau? Peut-être essayer 'this.resultsChanged $ .next (Array.from (json));' – martin

Répondre

0

Prenez note de la différence entre le sujet et BehaviorSubject:

Sujet se comporte comme un bus d'événements et ne tient pas de données.

BehaviorSubject peut agir comme un bus d'événement, mais aussi revenir la dernière valeur dans le flux lors de la souscription.

à votre service votre peut simplement déclarer:

public mySubject = new BehaviorSubject(null); 

Maintenant, vous pouvez l'utiliser pour effectuer les opérations suivantes:

this.testDataService.mySubject.subscribe(
    res => console.log(res), 
    error => console.log(error) 
); 
this.testDataService.mySubject.next('data'); 

C'est tout. J'espère que cela aide

+0

Le service de données doit contenir uniquement des données d'origine, car plusieurs composants utilisent les données, mais il semble qu'il conserve les données formatées après que mon composant le formate sans appeler le sujet suivant. –