Angular7-服务或订阅中的引用属性

时间:2019-03-06 20:26:42

标签: angular

我有一个带有属性的服务,我想引用该属性并在多个组件中进行更改。我可以通过将其分配给组件中的属性直接在组件中直接引用它,还是应该订阅一个可观察对象?我尝试了两种方式,当我在组件中对其进行修改时,两种方式似乎都改变了服务中的属性。

account.service.ts

export class AccountService {

constructor(private http: HttpClient) { }

testAccount: Account = {
    domain_name: "fortestaccoutnpage2",
    account_number: "fortestaccoutnpage2",
    bill_timing: "anniversary",
    }

getAccount(): Observable<Account> {
    return of(this.testAccount);
}

}

account.component.ts

export class AccountComponent implements OnInit {

constructor(private _accountService: AccountService) { }

changeAccountNumber() {
    this.account.account_number = "changed"
}

account: Account = this._accountService.testAccount;

grabAccount(): void {
    this._accountService.getAccount()
        .subscribe(account => this.account = account);
}

ngOnInit() {
    //this.grabAccount();
}

}

在上面的示例中,我基本上在组件中拥有account,引用服务中的testAccount,并且changeAccountNumber方法有效。我评论了让account订阅可观察对象的方法,但是当我这样做时,它也可以正常工作。一种方法比另一种更好?还是都很好?

3 个答案:

答案 0 :(得分:3)

最好订阅而不是直接从服务中引用。

订阅的优点在于,只有在调用observable时才会触发调用。因此,在这种情况下,这并不重要,因为您只是在使用测试对象。但是,如果您是从服务器拨打电话,则无法确定何时返回数据。因此,如果您在数据返回之前单击该按钮,则事情可能会发生。

此外,当前除了将帐户分配给媒体资源外,您什么也不做。哪个有效但是,如果稍后您想做其他事情,例如安装一个加载微调器,并在获取数据时将其关闭。您肯定需要利用可观察的东西。

编辑: 另外,更改组件本身内部的帐户可能不是一个好习惯。那肯定会起作用,但是如果您走那条路线,可能会导致一些令人困惑的错误,并使测试变得更加困难。最好集中进行更改。我建议向服务中添加一个方法changeAccountNumber(newNumber),该服务将使用更改后的帐户值推出一个新的可观察项。有点花哨,但它更具可测试性,我认为它更易于维护。

答案 1 :(得分:0)

grabAccount(): void {
    this._accountService.getAccount()
        .subscribe(account => this.account = account);
}

在这里,您将account(即_accountService.testAccount)的值分配给this.account。 因此this.account_accountService.testAccount是对内存中同一对象的引用。改变一个总是会影响另一个。

为避免这种情况,您可以在将对象分配给this.account

之前简单地对其进行克隆

这是执行此操作的简单方法:

grabAccount(): void {
    this._accountService.getAccount()
        .subscribe(account => this.account = JSON.parse(JSON.stringify(account)));
}

或者为避免代码重复,您可以在服务中进行克隆

getAccount(): Observable<Account> {
    return of(JSON.parse(JSON.stringify(this.testAccount)));
}

如果您有更复杂的对象(例如,具有Date值),则此克隆方法将不起作用

How do I correctly clone a JavaScript object?

答案 2 :(得分:0)

使用Rxjs中的行为主体实现,声明您的服务并安装行为主体,在创建另一个变量asObserver之后,您必须在目标组件中使用行为主体实现的下一个方法,以将最新的更改发送给行为服务中的主题,以后您可以订阅U想要该信息的任何组件

检查此触发 https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

和这个 http://reactivex.io/rxjs/manual/overview.html

尝试一些事情,等我可以更好地帮助您