2016-12-19 28 views
2

BehaviorSubjectを持つコンポーネントでresponseの値を取得できません。私はそれを手に入れてそれを渡す。BehaviorSubject RxJs angular2

私はルートガードのサービスからHTTPをトリガーしています。

サービス:

@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(); 
      } 
     ); 
    }); 
} 

コンポーネント:

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:それはちょうどHTTPのparams ...のクエリのparamをgetingだ

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

ガード:

@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) 
    } 
} 

私もNgZoneを試みるが、私はわからないんだけど、それは正しい方法である:すべての

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

何の問題、あなたを持っている?あなたは何のエラーを言及することができます。 –

+0

'load()'はどこにありますか?なぜあなたは非常に多くのネストされたオブザーバを使用しますか? – Meir

+0

エラーが表示されない...データをレンダリングしない...コンポーネントでHTTP応答を取得できない。 ルートガード(canActivate)でload()が正しく呼び出されました。 –

答えて

2

:まず、観察の内側に別の観測可能に加入しないでください。代わりに、ストリームとしてそれを書く:

@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)); 
} 

そして第二:

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

ngOnInit(): void { 
    // ...nothing to do here 
} 
を手動代わり async -pipeを使用し、クラスメンバーに結果を書き込むために無限のストリームにサブスクライブしないでください

テンプレート:

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

あなたの負荷の問題が解決しない場合は、あなたが共有したい場合がありますapi.sendメソッドの内容(それが確実に呼び出されていない限り)

一つの可能​​性は、あなたが次のことをしようとする場合があり、ngZoneの外で実行されている非同期メソッドを持っているだろう:

+0

まず、あなたの努力に感謝します、ありがとうございます。あなたが書いたことすべてを試してみる。あなたは「観察可能なものの中で観察可能」について正しい。 ngOnDestroyで購読を停止したコンポーネントのコードはすべて提供していませんでした。 APIはきれいで、私がサービスで 'console.log(temp)'を実行したときに、空の配列を取得するコンポーネントではなく、必要なデータが得られます。私はコンソールに何のエラーもないので、何をすべきかわからないので、アドバイスが私を助けます。私はそれが無関係であるか分からないが、私は野心的にこのアプリをrc6から4.0.0-beta.0に更新し、このBehaviorSubjectを除いてすべてがうまくいっている。 –

+0

また、 'NgZone'を試してみましたが、正しい方法であるかどうかは分かりません...メインポストの編集を確認してください... –

+1

ngZone.runで.next呼び出しをラップするだけで済みます。コールバックの多くの層の必要性:) – olsn

関連する問題