How can I create a variable in a service that gets its data from a promise yet is shared between two components?

心不动则不痛 提交于 2019-12-01 12:44:00

While it can probably be done with Promises, I can answer in the form of Observables at the very least, if you're of a mind to read about them...

Given ComponentA and ComponentB both looking at a SharedService for their source of SomeObject[] data:

The service:

import { Injectable } from '@angular/core';
import { Observable, Observer } from 'rxjs/rx';
import 'rxjs/add/operator/share';

import { SomeObject } from './some-object';

@Injectable()
export class SomeService{
    SharedList$: Observable<SomeObject[]>;
    private listObserver: Observer<SomeObject[]>;

    private sharedList: SomeObject[];

    constructor(private http: Http){
        this.sharedList = [];
        this.SharedList$ = new Observable<SomeObject[]>(x => this.listObserver = x).share();
    }

    getList(){
        // Get the data from somewhere, i.e. http call
        this.http.get(...)
            .map(etc)
            .subscribe(res => {
                this.sharedList = res;
                this.listObserver.next(this.sharedList);
            });
        // the important part is after getting the data you want, observer.next it
    }

    addItem(item: SomeObject): void {
        this.sharedList.push(item);
        this.listObserver.next(this.sharedList);
    }
}

Components then have:

import { Component, OnInit } from '@angular/core';
import { Observable, Observer } from 'rxjs/rx';

import { SharedService } from './some.service';

import { SomeObject } from './some-object';

@Component({...})
export class CommponentA implements OnInit {
    private list: SomeObject[];

    constructor(private service: SharedService){
        this.list = [];
    }

    ngOnInit(){
        this.service.SharedList$.subscribe(lst => this.list = lst);
        this.service.getList();
    }

    private onClick(item: SomeItem): void {
        this.service.addItem(item);
    }
}

ComponentB would look similar - subscribing to the same SharedList$ property on the service. When the service's getList() method is called, and it pushes a new SomeObject[] through the observables (this.listObserver.next(..)), the components subscribed to that property will be able to read the value pushed to it.

Edit: Exposed an addItem method on the service that the components can call to push items to the list. The service then pushes it through the observable, (this.listObserver.next(...)) in the same style as when getting the data through x other method (i.e. http).

@Krenom's answer was corrrect. with one import needing to be changed on my setup.

I needed import { Observable, Observer } from 'rxjs/Rx';import { Observable, Observer } from 'rxjs/Rx';

In your component

//set favorites
    getFavorites(): void{
        this.favoriteService
            .getFavorites()
            .then(favorites => this.favoriteService.favorites = favorites);
    }  

// get favorite
this.favorites = this.favoriteService.favorites;//access it from service
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!