必须是非常基本的东西,但是我被卡住了。
简而言之-我有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();
});
获取它。在这种情况下,它的工作原理。
答案 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;
});
}
}