oooyaya
oooyaya

Reputation: 1803

Sharing an observable/subject in Angular2

EDIT: For what it's worth, I've learned that the SharedService is getting initialized twice. I suspect I'm working with separate instances, which is why the .subscribe() is limited only to the initiator. I don't know how to correct this... I thought everything was a singleton in Angular2?

I have two components. I want either component to be able to POST through a service, and have both components receive the response.

The two components are pretty basic and essentially identical for the demonstration of this issue. Nothing really big to see here but here they are just in case:

Foo Component

@Component({
    selector: "foo",
    providers: [SharedService]
})

export class FooComponent {
    constructor(private _api:API, private _service:SharedService) {
        this._service.data$.subscribe(
            response => console.log("FOO!", response)
            // error not required here since the service handles it for all dependents.
        );
    }

    doSomething(values) {
        this._service.post(values);
    }
}

Bar Component

@Component({
    selector: "bar"
})

export class BarComponent {
    constructor(private _api:API, private _service:SharedService) {
        this._service.data$.subscribe(
            response => console.log("BAR!", response)
            // error not required here since the service handles it for all dependents.
        );
    }

    doSomething(values) {
        this._service.post(values);
    }
}

The SharedService is where I've been trying to get things right.

@Injectable()
export class SharedService {
    private _observer: Observer<Response>;
    public data$;

    // i wrapped Http in an API service.  it does the following:
    // 1.  convenience methods like .map() for the observables
    // 2.  adding headers to every request so that i don't need to do that for every service
    // 3.  takes the first parameter e.g. "login" and converts it to a full endpoint
    // 4.  converts the "values" object in to a body string

    constructor(private _api: API) {
        this.data$ = new Observerable(observer = this._observer = observer).share();
    }

    post(values:IValues) {
        this._api.post("foobar", values).subscribe(
            response => this._observer.next(response),
            error => console.log("foobar failure", error);
        );
    }
}

No matter what I try, I get only the success condition of the invoking component. So if I trigger the service from "Foo", I get "FOO!" and if I invoke it from "Bar", I get "BAR!".

Ideally, I could invoke it from "Foo" and receive back "FOO!" and "BAR!". The order of these responses doesn't really matter.

Upvotes: 1

Views: 328

Answers (1)

oooyaya
oooyaya

Reputation: 1803

Problem was that I had this and didn't realize it:

@Component({
    selector: "foo",
    providers: [SharedService] // only existed on one of them
})

@Component({
    selector: "bar"
})

Which created two instances. Working code is just:

@Component({
    selector: "foo"
})

@Component({
    selector: "bar"
})

Upvotes: 2

Related Questions