Reputation: 11
Not been doing Angular2 for long, so apologies if I'm not understanding observables correctly ... in a component I'm subscribing to getData which sits in a service class. What I want is for the http get to call and emit changes automatically back to the caller/subscriber when url changes (and maybe any other URL parameters for that matter). How can this be achieved? Am I not understanding observables correctly maybe?
@Injectable()
export class HttpService {
url: string;
constructor(
private http: Http
) {}
getData() {
return this.http.get(`${this.url}`)
.map((res:Response) => res.json());
}
setUrl(url) {
this.url = url;
}
}
Upvotes: 0
Views: 503
Reputation: 14087
With your implementation, getData()
uses whatever value this.url
holds at the time getData() is invoked. In other words, if you change this.url
AFTER you called getData()
, nothing will happen.
To do what you describe, you need to wrap the stream of different URLs inside an observable:
import {Subject} from 'rxjs/Subject';
@Injectable()
export class HttpService {
// The `url` property is replaced with an observable emitting a stream of URLs.
private _urlsStream: Subject<string> = new Subject<string>();
constructor(private http: Http) {}
// The http.get() now gets its urls from the url stream.
// Every time a new url is pushed to the stream, a new request is executed.
getData() {
return this._urlsStream.asObservable()
.mergeMap((url: string) => this.http.get(url))
.map((res: Response) => res.json());
}
setUrl(url) {
// Setting an url pushes the given url to the stream.
this._urlsStream.next(url);
}
}
This code is definitely more involved than the original version. I've added comments to clarify but if you're new to RxJS I highly suggest you spend some time reading the manual and watching some tutorials.
You'll want to learn about:
Subject
, which is a special type of observable that can both emit values and be subscribed to).mergeMap()
to "project" one observable - the stream of URLs - into another observable - the HTTP requests).Upvotes: 4