首页 > 解决方案 > Angular 6 手表数据从第 3 次服务更改

问题描述

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

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

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

例子:

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

去拿它。在这种情况下,它的工作。

标签: angulartypescript

解决方案


为了订阅某事,该某事需要是一个 Observable。为此,我们使用 Rxjs 之类的库。有许多 rxjs 可观察对象,例如 Subjects、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
    }
}

现在,您的第二个 Service 将始终拥有 Service0 提供的最新数据。

我还想指出,如果您在组件中使用它,那么在没有任何数据泄漏的情况下实际做到这一点的最佳做法是取消订阅 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 中执行此操作,因为您在构造函数中进行了订阅,并且该订阅只会在该服务的生命周期内持续。该构造函数只会被调用一次。如果该服务不是单例,那么您将必须实现相同的逻辑,因为您可能必须创建该服务的多个实例。在Angular.io阅读关于单例的信息。我希望我给了你一个答案,以帮助你完成你的工作。如有任何问题,请随时与我联系。

干杯


推荐阅读