Angular 6手表数据来自第三服务的变化

时间:2018-06-21 14:22:27

标签: angular typescript

必须是非常基本的东西,但是我被卡住了。

简而言之-我有3个服务:service0,service1,service3。 Service1存储数据,Service 2和3使用它。

我想从两个服务中订阅service1的data属性的更改。我该怎么办?

示例:

export class Service0 implements OnDestroy {
  constructor(private service1: Service1) { }
  add(data): boolean { this.service1.addData(data); }
}

export class Service1 implements OnDestroy {
  data: Data;
  constructor() { }
  get data() { return this.data }

  addData(data) {
     if (this.servers.findIndex(el => el.hostname === s.hostname) === -1){    
        this.data.push(s);
     }
  }
}

export class Service2 implements OnDestroy {
  data: Data;
  constructor(private service1: Service1) { this.data = this.service1.data; }
}

更新: 我尝试了这个,应该可以工作(数据服务):

import {Observable, of} from 'rxjs';

export class Service1 {
  data: Data[];

  constructor() { }
  get data() { return this.data }

  addData(data) {
     if (this.servers.findIndex(el => el.hostname === s.hostname) === -1){    
        this.data.push(s);
     }
  }

  getData(): Observable<Data[]> {
     return of(this.data)
  }
}

export class Service2 implements OnDestroy {
 data: Data[];
 constructor(private service1: Service1) { 
    this.service1.getData().subscribe(data=>{
       this.data = data
       console.log(this.data)
    })  
 }
}

添加对象后即触发,但是在这种情况下,console.log(this.data)仅在浏览器控制台中显示对象数组,而JSON.stringify(this.data)并试图调用属性-显示对象是空的。 仍然更喜欢这种解决方案,但不知道为什么会发生这种情况?

与此同时,一旦dataChanges = new Subject();中的数据被更改,我便使用Service1发出事件,然后

this.servers1.serversChanges.subscribe(() => {
  this.data = this.service1.getData();
});

获取它。在这种情况下,它的工作原理。

2 个答案:

答案 0 :(得分:2)

为了订阅某物,某物必须是可观察的。为此,我们使用Rxjs之类的库。有很多rxjs Observable,例如主题,BehaviorSubjects,AsyncSubjects等。您可以在此处rxjs

了解更多信息

下面的示例显示了如何实现简单的Observable Data Service!

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

Injectable()
export class Service0  {
    data: BehaviorSubject<string[]>;
    constructor() {
        this.data = new BehaviorSubject<string[]>([]);
    }
    getData() {
        // Logic to get data from an http call
        // On Successful response
        this.data.next(responseData);
    }
}

现在,您可以将该服务注入其他任何服务,组件等,并轻松订阅数据。

import { Injectable } from '@angular/core';
import { Service0 } from '../service0.ts';

Injectable()
export class Service1  {
    data: string[];
    constructor(private service0: Service0) {
        service0.data.subscribe(data => {
            this.data = data;
        });
    }
    dataFunction() {
        // do stuff with data
    }
}

现在,您的第二个服务将始终具有将从Service0提供的最新数据。

我还要指出,如果您在Component中使用它,则在不造成任何数据泄漏的情况下实际执行此操作的最佳做​​法是也取消订阅Observable。像这样:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { Service0 } from '../service0.ts';

@Component({
    selector: 'my-component',
    templateUrl: './my-component.component.html',
    styleUrls: ['./my-component.component.scss']
  })
export class MyComponent implements OnInit, OnDestroy  {
    data: string[];
    dataSubscription: Subscription;
    constructor(private service0: Service0) { }
    ngOnInit() {
        this.dataSubscription = this.service0.data.subscribe(data => {
            this.data = data;
        });
    }
    ngOnDestroy() {
        this.dataSubscription && this.dataSubscription.unsubscribe();
    }
}

您无需在Singleton Service中进行此操作,因为您在构造函数中进行了订阅,并且该订阅仅会在该Service的生命周期内持续。该构造函数将仅被调用一次。如果该服务是单例服务,那么您将必须实现相同的逻辑,因为您可能必须创建该服务的多个实例。在Angular.io上了解有关Singletons的信息。 希望我给您一个答案,以帮助您完成工作。如有任何问题,请随时与我联系。

欢呼

答案 1 :(得分:1)

好的,所以我在注释中添加了一些想法,但这是代码:

export class Service0 implements OnDestroy {
    constructor(private service1: Service1) {
        // In case when you only inform without passing data
        this.service1.dataChanges.subscribe(() => {
            // This service doesn't have 'data' member so do something else
        });

        // With passed data
        this.service1.dataChanges.subscribe((data) => {
            // This service doesn't have 'data' member so do something else
        });
    }

    add(data): boolean {
        this.service1.addData(data); // Could be changed now to use that setter
    }
}

export class Service1 implements OnDestroy {
    _data: Data;
    dataChanges = new Subject();

    constructor() {
    }

    get data() {
        return this._data;
    }

    set data(value) {
        this._data = value;
        this.dataChanges.next(); // or even pass here new value
    }
}

export class Service2 implements OnDestroy {
    data: Data;

    constructor(private service1: Service1) {
        this.data = this.service1.data;

        // In case when you only inform without passing data
        this.service1.dataChanges.subscribe(() => {
            this.data = this.service1.data;
        });

        // With passed data
        this.service1.dataChanges.subscribe((data) => {
            this.data = data;
        });
    }
}