2016-10-10 2 views
5

Я использую Angular CLI + Firebase + AngularFire2, пытающийся выяснить, как запросить один объект из Firebase с помощью ключа.Запрос одного объекта Firebase ключом из службы

Основной поток должен состоять в том, чтобы показать список элементов, а затем щелкнуть по элементу, чтобы отобразить подробный вид для этого конкретного элемента.

Это должно быть довольно распространенным вариантом использования, но документы AngularFire 2, похоже, не дают ясных примеров того, как я мог это сделать.

Я пытаюсь использовать сервис для запроса элементов, но я не могу заставить его работать.

Компонент

// COMPONENT 

import { Component, OnInit, OnDestroy } from '@angular/core'; 
import { Router, ActivatedRoute, Params } from '@angular/router'; 
import { AngularFire, FirebaseObjectObservable} from 'angularfire2'; 
import { Subscription } from 'rxjs'; 
import { ItemsService } from '../items.service'; 

@Component({ 
    selector: 'app-item-detail', 
    templateUrl: './item-detail.component.html', 
    styleUrls: ['./item-detail.component.css'] 
}) 
export class ItemDetailComponent implements OnInit, OnDestroy { 

    private subscription: Subscription; 
    private item; 

    constructor(private af: AngularFire, 
       private route: ActivatedRoute, 
       private router: Router, 
       private itemsService: ItemsService) { } 


    ngOnInit() { 
    this.subscription = this.route.params.subscribe(
     (param: any) => { 
     let id = param['id']; 
     console.log('Key: '+ id); 
     this.item = this.itemsService.getItem(id); 
     } 
    ); 
    } 

    ngOnDestroy() { 
    this.subscription.unsubscribe(); 
    } 

} 

Сервис

import { Injectable } from '@angular/core'; 
import { Headers, Http, Response } from "@angular/http"; 
import { AngularFire, FirebaseObjectObservable, FirebaseListObservable, FirebaseApp } from 'angularfire2'; 
import 'rxjs/Rx'; 

@Injectable() 
export class ItemsService { 

    private items: FirebaseListObservable<any[]>; 
    private item: FirebaseObjectObservable<any>; 

    constructor(private af: AngularFire) {} 

    getItems(num) { 
    this.items = this.af.database 
     .list('/items', { query: { limitToLast: num | 20} }) 
     .map((arr) => { return arr.reverse() }) as FirebaseListObservable<any[]>; 
    return this.items; 
    } 

    getItem(id: string) { 
    this.item = this.af.database.object('/items/'+id); 
    this.item.subscribe(item => { 
     console.log(item); 
     return item; 
     }); 
    } 

} 

ответ

2

Это следует сделать это:

// COMPONENT 
 

 
import { Component, OnInit, OnDestroy } from '@angular/core'; 
 
import { Router, ActivatedRoute, Params } from '@angular/router'; 
 
import { AngularFire, FirebaseObjectObservable} from 'angularfire2'; 
 
import { Subscription } from 'rxjs'; 
 
import { ItemsService } from '../items.service'; 
 

 
@Component({ 
 
    selector: 'app-item-detail', 
 
    templateUrl: './item-detail.component.html', 
 
    styleUrls: ['./item-detail.component.css'] 
 
}) 
 
export class ItemDetailComponent implements OnInit, OnDestroy { 
 

 
    private subscription: Subscription; 
 
    private item; 
 

 
    constructor(private af: AngularFire, 
 
       private route: ActivatedRoute, 
 
       private router: Router, 
 
       private itemsService: ItemsService) { } 
 

 
    
 
    ngOnInit() { 
 
    // get id synchronously, don't need it more then once 
 
    const key: string; 
 
    this.route.params.take(1).subscribe(param => key = param["id"]); 
 
    this.subscription = this.itemsService.getItem(id) 
 
     .subscribe(item => this.item = item) 
 
    } 
 

 
    ngOnDestroy() { 
 
    this.subscription.unsubscribe(); 
 
    } 
 

 
} 
 

 

 
@Injectable() 
 
export class ItemsService { 
 
    ... 
 

 
    getItem(id: string) { 
 
return this.af.database.object('/items/'+id); 
 
    } 
 

 
}

Попробуйте подписаться на Observable, где вам нужны данные. Ваши методы обслуживания должны возвращать Observable, а не Subscription (если у вас действительно нет веских оснований для этого).

+0

Благодарим за это. Я изменил const на let, поскольку он продолжал жаловаться, что объявления const должны быть инициализированы и использоваться getItem (ключ), а не идентификатор. Я также должен был объявить private item = {}. Теперь он работает, но я получаю задержку 5-7 секунд до появления данных. – LifeOnLars

+0

Остальная часть страницы загружается довольно быстро, но общее время составляет 10-11 секунд. Не уверен, что это медленная установка локального разработчика, или это просто не очень хороший способ запроса объекта. Количество данных тривиально, в выборке данных всего 8 текстовых узлов. В настоящее время представление списка загружает одни и те же данные, и это намного быстрее. Разве мы не собираемся извлекать объекты по $ key из Firebase? – LifeOnLars

+0

Это проблема CLI https://github.com/angular/angular-cli/issues/1980, как только вы загружаете предварительно скомпилированное приложение на сервер, оно будет быстрым. Вы можете проверить Dev Tools> Network, а затем фильтровать только для показа трафика WebSocket (WS) ... – Sasxa

Смежные вопросы