I'm new to Angular 4, so I accept that I may be better off changing my approach.
What I have is this:
ngOnInit() {
this.route.paramMap
.switchMap((params: ParamMap) => {
var id = +params.get('id');
return this.service.getOne(id);
}).subscribe(data => {
if (data.clientID === 0) {
data.clientID = +this.route.snapshot.queryParams["parentId"];
}
this.model = data;
},); // Subscription
this.lookupService.getList("clients").then(data => {
this.clients = data;
}); // Promise
}
On the client-side, I need to make another server call, but only when I have data from both of the calls above. In other words, I need the Subscription
to complete (well, not complete but set the value) and the Promise
to complete.
Is there something like a Promise.all
that would work to also ensure this.model
has been set in the Subscription
call?
EDIT: I could run these in series, but for performance reasons, I want to run them in parallel.
EDIT 2: The Promise
was intended to load lookup data to populate a dropdown only once. The Subscription
was intended to change the main model on each change of "id" in the URL .
Use .zip()
on the promise and the model-fetching observable. It will output an array of results that you can use to populate local class properties. At this point you can call your 3rd function (the local filter). Once the promise completes, so will .zip
, so this chain has only one output.
Once .zip()
completes, listen to new route parameters and fetch corresponding models. As they arrive, set your local class property and run your local filter
Subscribe to trigger the whole chain.
ngOnInit(){ // Will run getOne() with every new parameter let getModelForParam = this.route.paramMap.switchMap( params => this.service.getOne(+params.get('id')) ).share(); // Zip will wait for both below to produce, then output an array of results // and complete (since getList() promise completes after one call) Observable.zip( this.lookupService.getList('clients'), getModelForParam ).do(results => { // capture results in order of .zip() arguments this.clients = results[0]; this.model = results[1]; this.localFilter();// call the filter }).concat( // this part executes once .zip() completes getModelForParam // continue fetching models for new params ).subscribe(model => { this.model = model; this.localFilter(); }) }
You can use Observable.forkJoin
, which is equivalent to Promise.all
.
Observable.forkJoin(this.route.paramMap
.switchMap((params: ParamMap) => {
var id = +params.get('id');
return this.service.getOne(id);
}), Observable.fromPromise(this.lookupService.getList("clients")))
.subscribe((arrayOfResults) => {
[firstCallResult, secondCallResult] = arrayOfResults;
this.model = firstCallResult;
});
EDIT:
To fulfill the part about updating parameters, we can use the Observable.combineLatest
operator:
About Observable.combineLatest
Since it emits whenever one of the source observables emits, the subscribe block will be executed. Since the other observable is from a promise it will complete and not emit more values so this.lookupService.getList() will not be called again.
Observable.combineLatest(this.route.paramMap
.switchMap((params: ParamMap) => {
var id = +params.get('id');
return this.service.getOne(id);
}), Observable.fromPromise(this.lookupService.getList("clients")))
.subscribe((arrayOfResults) => {
[firstCallResult, secondCallResult] = arrayOfResults;
this.model = firstCallResult;
// do whatever else is needed
});
You can do something like
ngOnInit() {
this.lookupService.getList("clients").then(data => {
this.clients = data;
this.route.paramMap
.switchMap((params: ParamMap) => {
var id = +params.get('id');
return this.service.getOne(id);
}).subscribe(data => {
if (data.clientID === 0) {
data.clientID = +this.route.snapshot.queryParams["parentId"];
}
this.model = data;
==>Call ur method here!!!
},); /
}); // Promise
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.