2017-05-13 22 views
0

H、rxJs observableを正しく使用する上で問題があります。私の必要条件は、ブックにあるすべてのチャットルームを取得することです(部屋が利用できない場合は、新しいチャットルームを1つ作成してください)。 以下のコードを使用しています。観測可能なフォーク結合が機能しない

私のチャットコンポーネント

@Component({ 
selector: 'chat', 
templateUrl: './chat.component.html' 
}) 
export class ChatComponent implements OnInit { 
this.selectbookStream.subscribe(bookId=> 
{ 
this.chatService.getRooms(book id) 
    .subscribe(rooms => { 
     console.log("in chat component"); 
     console.log(rooms); 
     this.rooms = rooms; 
    }); 
}) 
} 

マイチャットサービス

@Injectable() 
export class ChatService { 
    public getRooms(bookID) { 
     console.log("in get rooms") 
     return this.thisPartyChatService.createRooms(bookID).map(r=>r) 

    } 
} 

サードパーティチャットサービス

public createRooms(bookID: string): Observable<any> { 
let rooms = []; 

this.modelService.getBookDetails(bookID).subscribe(book=> { 

    this.getRoom(book.name).subscribe(r => { 
    if (Object.keys(r).length === 0) { 
    rooms.push(this.createRoom(book.name).map(res=>res)) 
    } else { 
    // rooms.push(Observ) 
     rooms.push(Observable.of({ 
     'id': r.id, 
     'type': r.type, 
     'title': r.title, 
     'name': r.title, 
     'created': r.created 
     }) 
    ) 
    } 

    }) 

}); 
return Observable.forkjoin(rooms); 

} 


public createRoom(bookID: string): Observable<any> { 
    return this.http.post(this.apiUrl.room, { 'title': bookID, 'teamId': 
     teamId }, this.generateHeader()).map(res => res.json); 
    } 

    public getRoom(modelId: string): Observable<any> { 
    this.roomTitle = modelId; 
    // search all rooms in CISCO sparck and match with modelId 
    return this.http.get(this.apiUrl.room, this.generateHeader()) 
     .map(this.findRoom); 
    } 


    private findRoom(res: Response) { 
    let body = res.json(); 
    let room: any; 
    body.items.forEach(element => { 
    if (element.title == this.roomTitle) 
    return element; 
    }); 
    return {}; 
} 
+0

私はなぜあなたが 'forkJoin'を使っているのか分かりません。 'defaultIfEmpty'がほしいと思うようです。 'forkJoin'は複数のオブザーバを並列に(理論的にはとにかく)実行し、その結果を予想通りに組み合わせるためのものです。 –

+0

私は非常に新しいrxJSです。私の場合、defaultEmtpyの使い方について少し詳しく説明できますか? –

+0

ソースから要素を生成します。ソースが空の場合は、指定されたデフォルト値を返します。 Ex: 'Observable.from([]).defaultIfEmpty(1)'は '1'を返します。 –

答えて

0

それはあなたが呼び出す必要があるため、サービスが呼び出されていないこともありそれは関数の内部にあります。たとえば、コンポーネントimplements OnInitはそうあなたがその関数内で自分のサービスコールを入れて、コンポーネントは、このように終わるかもしれない:

@Component({ 
    selector: 'chat', 
    templateUrl: './chat.component.html' 
}) 
export class ChatComponent implements OnInit { 

    public rooms = []; 

    public ngOnInit() { 

     this.selectbookStream.subscribe(bookId => { 
      this.chatService.getRooms(book id) 
       .subscribe(rooms => { 
        console.log("in chat component"); 
        console.log(rooms); 
        this.rooms = rooms; 
       }); 
     }) 
    } 
} 
1

私はこの問題はcreateRooms()方式の構造であると思います。基本的には、以下の持っている:

public createRooms(bookID: string): Observable<any> { 
    let rooms = []; 

    this.modelService.getBookDetails(bookID).subscribe(book => { 
     this.getRoom(book.name).subscribe(...); 
    }) 

    return Observable.forkjoin(rooms); 
} 

ネスティングsubscribe()呼び出しは常に警告サインです。

getBookDetailsまたはgetRoomは非同期関数なので、コードがreturn Observable.forkjoin(rooms)になると、roomsの配列は常に空になります。

コードを再構成することをお勧めします。たとえば、このように(私はそれをテストしなかったが、あなたはポイントを得るべきである)。

public createRooms(bookID: string): Observable<any> { 
    return this.modelService.getBookDetails(bookID) 
     .concatAll() 
     .concatMap(book => this.getRoom(book.name)) 
     .concatMap(room => { 
      if (Object.keys(r).length === 0) { 
       return Observable... 
      } else .... 

     }); 
} 
+0

私の.modelService.getBookDetailsは本の配列を与える、私はチェックし、配列のすべての要素の部屋を作成する必要があります。 concatMapを使ってみましたが、期待通りの結果を得られませんでした。 –

+0

'.concatAll()'を使って、配列を個別のエミッションに展開することができます。 – martin

+0

concatAllは私のために働いていません..私はそれを間違って使用しているかもしれません、そのコンパイルエラーを投げる –

関連する問題