2016-12-19 24 views
2

Ich bekomme nicht den Wert der Antwort in einer Komponente mit BehaviorSubject. Ich habe es und gebe es im Dienst.BehaviorSubject RxJs angular2

Ich trigger HTTP aus Service auf Route Guard.

Service:

@Injectable() 
export class ProjectsService { 
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]); 

load(clientId: string, active: boolean): Observable<boolean> { 
    return new Observable<boolean>((obs) => { 
     this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId).subscribe(
      res => { 
       let temp = []; 
       res.forEach(a => temp.push(new Project(a))); 

       if (active) this.projects.next(temp); 
       else this.externalProjects.next(temp); 
       obs.next(true); 
       obs.complete(); 
      }, 

      err => { 
       obs.next(false); 
       obs.complete(); 
      } 
     ); 
    }); 
} 

Komponente:

ngOnInit(): void { 
    // todo: check why not to load already added 
    this._projectsListener = this._projectsService.projects.subscribe(a => { 
     this.showIntro = a.length ? false : true; 
     this.projects = a; 
    }); 
} 

HTML:

<div class="project" [hidden]="!showIntro" *ngFor="let project of projects> 
    {{project.title}} 
</div> 

Es ist nur Abfrage param Geting für HTTP params ... Wache:

@Injectable() 
export class ProjectsGuard implements CanActivate { 
    constructor(
     private _projectsService: ProjectsService, 
     private _router: Router) {} 

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { 
     return this._projectsService.load(next.params['id'], true) 
    } 
} 

Ich versuche auch, ein NgZone aber ich bin nicht sicher, dass es ein richtiger Weg:

load(clientId: string, active: boolean): Observable<boolean> { 
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId) 
     .map(res => { 
      let temp = res.map(a => new Project(a)); 

      this._ngZone.run(() => { 
       console.log('temp: ', temp); 
       if (active) this.projects.next(temp); 
       else this.externalProjects.next(temp); 
      }); 

      return true; 
     }) 
     .catch(() => Observable.of(false)); 
} 

enter image description here

+1

Welche Frage Sie bekam? Sie können erwähnen, welchen Fehler Sie bekommen. –

+0

Wo wird 'load()' aufgerufen? Warum benutzt du so viele verschachtelte Observable? – Meir

+0

Ich bekomme keinen Fehler ... einfach nur keine Daten gerendert ... kann HTTP-Antwort in einer Komponente nicht erhalten. load() wird beim Routenschutz (canActivate) ordnungsgemäß aufgerufen. –

Antwort

2

Zunächst einmal: auf einem anderen beobachtbaren innerhalb einer beobachtbaren nicht abonnieren Sie. Stattdessen schreiben Sie es als Stream:

@Injectable() 
export class ProjectsService { 
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]); 

load(clientId: string, active: boolean): Observable<boolean> { 
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId) 
     .map(res => { 
       let temp = res.map(a => new Project(a)); 

       if (active) { 
        this.projects.next(temp); 
       } else { 
        this.externalProjects.next(temp); 
       } 
       return true; 
      }) 
     .catch(() => Observable.of(false)); 
} 

Und zweitens: Seien Sie nicht manuell zu einem endlosen Strom subscribe das Ergebnis in eine Klasse-Mitglied zu schreiben, verwenden Sie die async -pipe statt:

public projects$: Observable<Project[]> = this._projectsService.projects; 
public showIntro$: Observable<boolean> = this.projects$ 
    .map(projects => projects.length > 0); 

ngOnInit(): void { 
    // ...nothing to do here 
} 

Die Vorlage:

<div class="project" [hidden]="!showIntro" *ngFor="let project of (projects$ | async)> 
    {{project.title}} 
</div> 
....somewhere else: 
<div *ngIf="showIntro$ | async">INTRO!</div> 

Wenn Ihr Laden Problem immer noch besteht, dann möchten Sie vielleicht teilen der Inhalt der api.send Methode (sofern das nicht sicher genannt wird).

Eine Möglichkeit, eine Asynchron-Methode zu haben wäre, die außerhalb des ngZone läuft, möchten Sie vielleicht dann folgendes versuchen: Ihre

+0

Zunächst einmal schätze ich Ihre Bemühungen, danke. Ich versuche all die Dinge, die du geschrieben hast. Sie haben recht, wenn Sie "beobachtbar" sind. Ich habe nicht den ganzen Code der Komponente zur Verfügung gestellt, wo ich mich bei ngOnDestroy abmelde. Die API ist sauber und wenn ich 'console.log (temp)' im Dienst habe, habe ich Daten, die ich will, aber nicht in einer Komponente, wo ich ein leeres Array bekomme. Ich habe keine Fehler in einer Konsole, also habe ich keine Ahnung was zu tun ist, jeder Rat wird mir helfen.Ich weiß nicht, ob es irrelevant ist, aber ich aktualisiere ambitioniert diese App von RC6 auf 4.0.0-Beta.0 und alles funktioniert gut außer diesem BehaviorSubject. –

+0

Und ich versuche auch 'NgZone', aber nicht sicher ist es ein richtiger Weg ... überprüfen Sie die Hauptpost bearbeiten ... –

+1

Sie müssen nur die .next Anrufe in eine ngZone.run wickeln - das sollte schon tun, nein Notwendigkeit für viele Schichten Rückrufe ect. :) – olsn

Verwandte Themen