如何组织Angular数据服务

时间:2018-05-22 04:28:29

标签: angular rxjs observable

我对Observables,Observers,Subjects,BehaviorSubjects,Services,injections等感到有些困惑。

我正在尝试制作一个简单的财务应用。我有一个事务服务,它从REST服务器获取数据,然后将其提供给其他可以在需要时更新它的服务。我可以获取列表事务组件(从getTransactions()获取其数据)以使用该服务进行更新,但我不知道如何获取编辑组件(从#34获取其数据; { {1}}"工作。

让组件使用整个阵列中的数据(读/写访问)以及只想使用阵列的单个元素播放的数据的最佳方法是什么?

这就是我现在所拥有的:(我已经改变了它,所以它目前已经坏了,但你可以看到我在做什么)

getTransaction(id)

我也做了这个演示,展示了我的目标: https://stackblitz.com/edit/angular-stackblitz-demo-dftmn3

这是来自Get one value from observable array

的后续问题

1 个答案:

答案 0 :(得分:4)

这是一个很好的问题。我知道一开始很难与RxJs一起工作,但是当你掌握RxJ时,它会非常强大。

BehaviorSubject可以实现您的目标。

让我们找出Subject是什么,然后转到BehaviorSubject

  

主题:相当于一个EventEmitter,是将值或事件多播到多个观察者的唯一方法

有关详细信息,请查看here

因此,我们知道Subject就像EventEmitter。当有人订阅它时,无论何时拨打subject.next(value),每个订阅者都将获得新值。但是,后期订阅者(意味着在调用Subject方法后订阅next)不会获得以前的值。这是BehaviorSubject将进入场景的地方。

就像Subject一样,但是当新订阅者订阅它时,它会发出先前的值。我们在您的代码中使用它。

export class DataBrokerService {
    // do not expose your subject to other classes
    private _transactions$: BehaviorSubject<Transaction[]> = new BehaviorSubject([]);
    // instead provide it as an observable
    public readonly transactions: Observable<Transaction[]> = this._transactions$.asObservable();

    needUpdate = true;

    constructor(private http: HttpClient) { }

    ngOnInit() {
    }

    // just return the observable
    getTransactions(): Observable<Transaction[]> {
        if (needUpdate) {
            this.updateTransactions();
        }
        return this.transactions;
    }

    // you can iterate over your transactions and filter them,
    // but DO NOT ever subscribe to it within a service. 
    // Otherwise, other classes won't be able to retrieve the value.
    getTransaction(id: number): Observable<Transaction> {
        return this.getTransactions().pipe(
            map(txns => txns.find(txn => txn.id === id))
        );
    }

    // when you need to update the transactions,
    // simply call this method
    updateTransactions() {
        this.http.get('transactions').subscribe(txns => {
            this.needUpdate = false;
            this._transactions$.next(txns);
        });
    }      
}