【问题标题】:Subscribing to a service from component in Angular 2+从 Angular 2+ 中的组件订阅服务
【发布时间】:2018-05-02 13:39:52
【问题描述】:

我有一个需要每秒返回日期的服务:

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 的新手,文档没有帮助。

【问题讨论】:

  • 您是否将该服务注册为app.module 的提供者?
  • 你应该returnsetInterval

标签: angular rxjs angular2-services angular2-observables


【解决方案1】:

你应该首先在你的服务函数中返回一个Observable

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

【讨论】:

    【解决方案2】:

    无需使用 Rx 实现 setInterval

    这是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());
      }
    }
    

    See it in StackBlitz

    Observable.interval() 将发出一系列整数 1, 2, 3, ...,您只需将其值丢弃 (() =&gt;) 并替换为 Date,使用 .map()

    您可以保持HeaderComponent 不变。

    注意:我已经删除了对this.mydate 的分配,因为它似乎 不需要。我注意到,当纯粹的功能解决方案就足够时,许多转向 Angular 的人会出于反射创建不必要的中间成员变量。如果我过于放肆而你需要它,你可以随时把它放回去。

    在 Angular 中你也不需要空的 constructor,所以我也删除了它。

    不过,您确实需要另外两个imports。

    【讨论】:

      【解决方案3】:

      您实际上并没有返回可观察对象,而是在getClock() 中返回void

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-23
        • 2021-10-07
        • 2018-10-06
        • 1970-01-01
        • 2017-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多