2017-03-08 1 views
0

Ich habe einen Angular2-Dienst wie folgt. Ich versuche, dies als einen gemeinsamen Dienst zwischen mehreren Komponenten zu verwenden. Wenn es darauf ankommt, sind die Komponenten direkt an die public books gebunden, und selectedBook properties Ich möchte die Liste der Bücher und das derzeit ausgewählte Buch auf dem Dienst zwischenspeichern und nur beim ersten Aufruf diese auffüllen.Angular2 versucht, Element in einem Array zu erhalten, bevor Array belegt ist

import { Injectable } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 

@Injectable() 
export class BookService { 

    public books: Book[]; 
    public selectedBook: Book; 

    constructor(private http: Http, 
     private router: Router) { 

     this.http.get('/api/book/list') 
      .subscribe(result => this.books = result.json() as Book[]); 
    } 

    public getBooks() { 
     return this.books; 
    } 

    public setSelectedBook(id) { 
     this.selectedBook = this.books.filter(x => x.id == id)[0]; 
    } 
} 

Das Problem ist, dass manchmal ich versuche, das Array zu lesen oder setSelecteBook(id) aufrufen, bevor das Array tatsächlich bevölkert wird, was einen Absturz verursacht. Ich habe versucht, ein Beispiel für die Verwendung von Observablen zu finden, aber ich kann kein Szenario finden, das nah genug an meinem ist, um herauszufinden, wie ich es anpassen kann, um mein Problem zu lösen.

+0

Sie müssen 'Bücher' im Konstruktor initialisieren:' this.books = [] ' –

+0

Dies verzögert nur den Absturz nach diesem Punkt. Ich brauche etwas, damit es darauf wartet, dass das books-Array den Popup-Vorgang beendet, und anschließend das ausgewählte Buch einstellt. –

Antwort

0

Dies initialisiert ein Array nicht, sondern teilt dem TypeScript-Compiler mit, dass diese bestimmte Eigenschaft von diesem Typ ist. Um ein Array tatsächlich zu haben, müssen Sie es initialisieren, anstatt undefined zu sein. Auf diese Weise die filter Funktion funktioniert:

@Injectable() 
export class BookService { 

    public books: Book[] = []; 
    //... 
} 
2

Sie können die Array-Bücher im Konstruktor mit einem leeren Array initialisieren.

Sie können auch eine Problemumgehung durchführen und die Länge vor dem Zugriff auf das Array überprüfen.

public setSelectedBook(id) { 
    if(this.books.length > 0) { 
     this.selectedBook = this.books.filter(x => x.id == id)[0]; 
    } 
} 
+1

Typescript hat nicht den sicheren Evaluierungsoperator '? .' –

+0

@ChristopherMoore hat den Operator korrekt. Aber ich schrieb den Null- und Längen-Check auf den langen Weg und alles was dazu führte war, dass die App an diesem Punkt abstürzte; Es setzt das ausgewählte Buch einfach nicht, wenn es angerufen wird. Ich brauche etwas, damit es darauf wartet, dass die Bücher [] zu Ende gehen und das ausgewählte Buch danach setzen. –

0

Als eine sauberere Lösung würde ich von Ihrem Buch-Detail-Komponente zum Beispiel auf die Service-Methode getBooksList abonnieren.

Führen Sie den api-Aufruf mit this.bookService.getBooksList aus, und sobald das Array geladen ist, wählen Sie das gewünschte Buch aus.

+0

Ich denke, ich folge, was Sie sagen, aber ich könnte ein wenig Code für die Klarheit verwenden. Außerdem möchte ich nicht jedes Mal, wenn sich das ausgewählte Buch ändert, die Bücher [] vom Server auffüllen. –

+0

Sie können dieses Repo von mir hier sehen: https://github.com/dkiriakakis/ng2-photoalbum Werfen Sie einen Blick in /src/app/components/photo-detail.component.ts – dkiriakakis

Verwandte Themen