2017-05-13 4 views
0

H, habe ich Probleme in richtig mit rxJs beobachtbar. Meine Anforderung ist, alle Chatrooms auf ein Buch zu bekommen (wenn das Zimmer nicht verfügbar ist, einen neuen Chatraum erstellen) Ich benutze den untenstehenden Code und die beobachtbare Komponente im Chat wird nie aufgerufen.Observable Gabel Join funktioniert nicht

meine Chat-Komponente

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

Mein Chat-Dienst

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

    } 
} 

Drittanbieter-Chat-Service

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

Ich bin mir nicht sicher, warum Sie 'forkJoin' though verwenden. Es klingt wie du willst 'defaultIfEmpty'. 'forkJoin' dient dazu, mehrere Observablen parallel (theoretisch sowieso) zu laufen und ihre Ergebnisse vorhersagbar zu kombinieren. –

+0

Ich bin sehr neu rxJS, können Sie etwas mehr Details zur Verwendung von defaultEmtpy in meinem Fall geben ..? –

+0

Es liefert Elemente aus der Quelle oder, wenn die Quelle leer ist, liefert es den angegebenen Standardwert. Bsp .: 'Observable.from ([]). DefaultIfEmpty (1)' ergibt '1'. –

Antwort

0

Es dass der Dienst, da Sie anrufen müssen nicht aufgerufen werden kann zu es innerhalb einer Funktion. Zum Beispiel Ihre Komponente implements OnInit so können Sie Ihren Service-Aufruf innerhalb dieser Funktion setzen und die Komponente Ende wie diese haben bis:

@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

denke ich, das Problem in der Struktur der createRooms() Methode. Grundsätzlich haben Sie die folgenden Schritte aus:

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

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

    return Observable.forkjoin(rooms); 
} 

Nesting subscribe() Anrufe ist immer ein Warnzeichen.

Ich denke, getBookDetails oder getRoom sind so asynchrone Funktionen, wenn der Code erreicht return Observable.forkjoin(rooms) die rooms Array immer leer ist.

Also ich würde Ihnen empfehlen, Ihren Code neu zu strukturieren. Zum Beispiel so (ich habe es nicht getestet, aber Sie sollten den Punkt verstehen).

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

mein .modelService.getBookDetails gibt Array von Büchern, ich muss überprüfen und erstellen Sie Räume für alle Elemente im Array. Ich habe versucht, mit concatMap und gab keine erwarteten Ergebnisse –

+0

Sie können '.concatAll()' verwenden, um das Array in separaten Emissionen zu entpacken. – martin

+0

concatAll funktioniert nicht für mich .. kann ich es falsch verwenden, seine werfenden Kompilierungsfehler –