Подписка на услугу из компонента Angular 2+ - PullRequest
0 голосов
/ 02 мая 2018

У меня есть служба, которая должна возвращать дату каждую секунду:

import { Injectable } from '@angular/core';

import {Observable} from 'rxjs/Observable';

@Injectable()
export class ClockService {

    mydate: Date;

  constructor() {
  }

  getClock(): Observable<any> {
      setInterval(()=>{
          this.mydate = new Date();
          return this.mydate;
      }, 1000);
  }

}

Я пытаюсь подписаться на функцию getClock() для обновления mydate в моем компоненте:

import { Component, OnInit } from '@angular/core';
import {ClockService} from './clock.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {



  constructor(private clockService: ClockService) { }

  ngOnInit() {
      console.log(this.clockService.getClock().subscribe(res => this.mydate = res));
  }

}

Я получаю ошибку, ERROR TypeError: Cannot read property 'subscribe' of undefined

Я новичок в Angular 2, и документы не помогают.

Ответы [ 3 ]

0 голосов
/ 02 мая 2018

Вы на самом деле не возвращаете наблюдаемое, а вместо этого void в getClock().

См. https://angular.io/guide/observables

Вместо этого сделайте что-то вроде этого:

import { Injectable } from '@angular/core';

import {Observable} from 'rxjs/Observable';

@Injectable()
export class ClockService {

  private $timer = new Observable(obs => {
      setInterval(() => {
          obs.next(new Date());
      }, 1000);
  });

  constructor() {
  }

  getClock(): Observable<Date> {
      return this.$timer;
  }

}
0 голосов
/ 02 мая 2018

Нет необходимости реализовывать setInterval с Rx.

Вот еще одна опция с Observable.interval, которая создает Observable, который выдает новое значение через заданный интервал, что именно то, что вы хотите сделать:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/map';

@Injectable()
export class ClockService {    
  getClock(): Observable<Date> {
      return Observable.interval(1000).map(() => new Date());
  }
}

Посмотреть в StackBlitz

Observable.interval() выдаст серию целых чисел 1, 2, 3, ..., значение которых вы просто отбрасываете (() =>) и заменяете на Date, используя .map().

Вы можете оставить свой HeaderComponent без изменений.

Примечание: я удалил присвоение this.mydate, потому что оно не кажется необходимым. Я заметил, что многие люди, переходящие в angular, создают ненужные промежуточные переменные-члены вне рефлекса, когда достаточно чисто функционального решения. Если я был слишком самонадеян и вам это нужно, вы всегда можете вернуть его обратно.

Вам также не нужен пустой constructor в Angular, поэтому я тоже убрал его.

Вам нужно нужны еще два import с.

0 голосов
/ 02 мая 2018

Сначала вы должны вернуть Observable в вашей сервисной функции.

getClock(): Observable<any> {
  return new Observable(observer => {
    setInterval(()=>{
      this.mydate = new Date();
      observer.next(this.mydate);
    }, 1000);
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...