Сервисный цикл Angular http

Сегодня столкнулся с новой проблемой в сервисах.

Я пытаюсь создать службу http, но когда я пытаюсь сохранить в своей службе объект Observable, возвращаемый http.get.map, мое приложение падает.

Я хотел создать «систему», в которой служба циклически обновляет данные, а компоненты, которые подписались на наблюдаемое, обновляют свои данные в соответствии с данными службы.

Вот код:

afficheur.component.ts :

import { Component } from '@angular/core';
import {HardwareService} from "../../services/hardware.service";

@Component({
    selector: 'afficheur',
    templateUrl: 'app/components/hardware/afficheur.component.html'
})
export class AfficheurComponent{
    public state: Boolean;
    constructor(private service: HardwareService){
        this.service
            .getHardware()
            .subscribe(data => (console.log(data), this.state = data.afficheur),
                error => console.log(error),
                () => console.log('Get etat afficheur complete'))
    }
}

hardware.service.ts :

import { Injectable, OnInit }              from '@angular/core';
import { Headers, Http, Response }          from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Injectable()
export class HardwareService implements OnInit{
    private apiUrl = 'http://10.72.23.11:5000';  // URL to web API

    private ressources: Observable<any>;

    constructor (private http: Http) {}

    ngOnInit() {
        this.loopupdate()
    }

    loopupdate(): void {
        setInterval(() => {
            this.update();
        }, 5000);
    }

    update(): void {
        this.ressources = this.http.get(this.apiUrl)
            .map(this.extractData)
            .catch(this.handleError);
    }

    getHardware(){
        return this.ressources;
    }

    private extractData(res: Response) {
        let body = res.json();
        return body || { };
    }
    private handleError (error: Response | any) {
        // In a real world app, you might use a remote logging infrastructure
        let errMsg: string;
        if (error instanceof Response) {
            const body = error.json() || '';
            const err = body.error || JSON.stringify(body);
            errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
        } else {
            errMsg = error.message ? error.message : error.toString();
        }
        console.error(errMsg);
        return Observable.throw(errMsg);
    }
}

приложение.модуль.тс :

    import { FormsModule } from '@angular/forms';
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpModule }    from '@angular/http';

    import { AppComponent } from './app.component';


    import { ROUTING } from './app.routes';
    import {HardwareService} from "./services/hardware.service";
    import {AfficheurComponent} from "./components/hardware/afficheur.component";
    import {HardwareListComponent} from "./views/hardwarelist/hardwarelist.component";


    @NgModule({
        imports: [ BrowserModule, ROUTING, HttpModule, FormsModule, HttpModule],
        declarations: [
            AppComponent,
            AfficheurComponent,
            HardwareListComponent
        ],
        bootstrap: [ AppComponent ],
        providers: [ HardwareService ]
    })

export class AppModule { }

Еще раз спасибо, что вы есть :D

РЕДАКТИРОВАТЬ :

У меня возникла ошибка при попытке запустить приложение:

ERROR TypeError: Cannot read property 'subscribe' of undefined

Я думаю, что это связано с инициализацией this.ressources, есть идеи?


РЕДАКТИРОВАТЬ 2: В моей службе:

initializePolling(){
        return IntervalObservable.create(5000)
            .flatMap(() => {
                return this.getHardware()
        });
    }

getHardware(): Observable<any> {
        return this.http.get(this.apiUrl)
            .map(this.extractData)
            .catch(this.handleError);
    }

Как я могу подписаться на это с помощью моего компонента? Я не знаю, какой метод я должен вызывать в своем компоненте для извлечения данных без нескольких вызовов, если у меня есть несколько компонентов.


person Jérémy JOKE    schedule 23.05.2017    source источник


Ответы (1)


Проблема в том, что ngOnInit(), как и в вашем классе Injectable, является хук жизненного цикла, который работает только с директивами и компонентами. Попробуйте вызвать this.loopUpdate() из конструктора класса Injectable. Вы можете узнать больше об этом в другом потоке/вопросе.

Если вы хотите установить интервал получения данных, сделайте это в классе компонента, а не в сервисе. В службе у вас должны быть только методы, которые возвращают Observables (в вашем случае) от вызова http.get().... Таким образом, у вас не будет возвращаемого неопределенного объекта и более многоразовой службы.

Кроме того, вот еще одна ссылка SO, которую вы можете посмотреть.

person Rax Weber    schedule 23.05.2017
comment
Я обновлю прямо сейчас свой пост с ошибкой, которую я получаю. Я использовал ngOnInit (), потому что я хотел, чтобы Observable инициировался, и я думаю, что проблема здесь в причине ERROR TypeError: Не удается прочитать свойство «подписаться» на undefined, есть идеи? - person Jérémy JOKE; 23.05.2017
comment
@JérémyJOKE Обновил мой ответ. - person Rax Weber; 23.05.2017
comment
Проблема в том, что все мои компоненты используют один и тот же сервис (провайдер), поэтому, если я создаю 2 afficheur.component, это умножает на 2 количество вызовов API. Вот почему я хотел, чтобы сервис зацикливался, а компоненты обновлялись в соответствии с данными сервиса. - person Jérémy JOKE; 23.05.2017
comment
@JérémyJOKE Добавил еще одну ссылку SO в мой ответ. - person Rax Weber; 23.05.2017
comment
Как мой компонент может подписаться на Observable (IntervalObservable)? Я не знаю, как это понять. Пост обновлен через 2 секунды - person Jérémy JOKE; 24.05.2017
comment
Я проголосую за ваш ответ, он решил исходную тему. Я открою новый, чтобы получить помощь по Observable и IntervalObservable. Еще раз спасибо. - person Jérémy JOKE; 24.05.2017