Angular2 пытается получить элемент в массиве перед заполнением массива

У меня есть сервис Angular2 следующим образом. Я пытаюсь использовать это как общий сервис между несколькими компонентами. Если это имеет значение, компоненты привязываются непосредственно к public books, а также selectedBook properties Я хочу кэшировать список книг и выбранную в данный момент книгу в сервисе и заполнять их только при первом вызове.

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];
    }
}

Проблема в том, что иногда я пытаюсь прочитать массив или вызов setSelecteBook(id) до фактического заполнения массива, что вызывает сбой. Я пытался найти пример того, как использовать Observables, но я не могу найти сценарий, достаточно близкий к моему, чтобы понять, как адаптировать его для решения моей проблемы.

3 ответа

Вы можете инициализировать массив книг в конструкторе пустым массивом.

Вы также можете сделать обходной путь и проверить длину перед доступом к массиву.

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

Это не инициализирует массив, оно просто сообщает компилятору TypeScript, что это определенное свойство относится к этому типу. На самом деле иметь массив, а не быть undefined, вы должны инициализировать его. Таким образом, filter Функция будет работать:

@Injectable()
export class BookService {

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

В качестве более чистого решения я бы подписался на ваш компонент book-detail, например, на сервисный метод getBooksList.

Выполните вызов API с использованием this.bookService.getBooksList и, как только загрузится массив, выберите нужную книгу.

Другие вопросы по тегам