Reputation: 3102
In angular i want to create a multiple subscribe sequence. When the first subscribe is complete do next subscribe. Similar to this.
this.globalCtrl.getSon().subscribe(
response => {
this.son= response;
},
error => {
console.log(error);
},
() => {
//DOESN´T ENTER IN THIS SUBSCRIBE
this.dashboardCtrl.getMarkers(this.son).subscribe(
response => {
this.markers = response["body"]["data"];
if (this.markers.length == 0) {
this.toast.fire({
type: "error",
title: "No hay datos geográficos del grupo seleccionado"
});
}
this.timezone = response["body"]["timezone"];
},
error => {
console.log(error);
}
);
The problem: Doesn't enter in the second subscription and the 'response' has data. ¿Anyone know how can i do that?
UPDATE
If i put second subscription inside response like this
this.globalCtrl.getSon().subscribe(
response => {
this.son= response;
this.dashboardCtrl.getMarkers(this.son).subscribe(
response => {
this.markers = response["body"]["data"];
if (this.markers.length == 0) {
this.toast.fire({
type: "error",
title: "No hay datos geográficos del grupo seleccionado"
});
}
this.timezone = response["body"]["timezone"];
},
error => {
console.log(error);
}
);
Works but view doesn´t show data. When i refresh the view data load properly, but in first load doesn´t load data.
UPDATE 2: USING SWITCH MAP
this.globalCtrl.getfather().pipe(
switchMap(son=> this.dashboardCtrl.getMarkers(son.toString()).subscribe( /ERROR
response => {
this.markers = response["body"]["data"];
if (this.markers.length == 0) {
this.toast.fire({
type: "error",
title: "No hay datos geográficos del grupo seleccionado"
});
}
this.timezone = response["body"]["timezone"];
},
error => {
console.log(error);
}
)
);
The propierty subscribe doesn´t exist in OperatorFunction
Maybe the observable cause the error
getFather(): Observable<any> {
return this.grupo.asObservable();
}
Upvotes: 0
Views: 915
Reputation: 8292
Having a subscription inside a subscription is called Flattening
In response to @DeborahK answer using switchMap
would work, but it would be a misuse of it. switchMap
would be a way to go if your first observable could change while there's a subscription already to it. Better approach would be to use mergeMap
also (previously) known as flatMap
mergeMap - Use it when you have an Observable whose results are another Observable
switchMap - Use it when you have an Observable that can change and whose results are another Observable
If your first Observable emits something, mergeMap wouldn't discard the previous Observable, therefore your inner subscription would still be subscribed to the previous one. In switchMap it would discard the previous Observable and inner subscription would subscribe to the inner one.
The solution:
import { mergeMap } from 'rxjs/internal/operators/mergeMap';
.......
.......
this.globalCtrl.getSon().pipe(
mergeMap((response) => {
this.son = response;
return this.dashboardCtrl.getMarkers(this.son)
})
).subscribe((res) => {
this.markers = response["body"]["data"];
});
Upvotes: 1
Reputation: 60596
It is recommended that you do not nest a subscribe inside another subscribe. It makes it difficult to manage and just about impossible to correctly unsubscribe. Instead, use switchMap
.
Here is an example from one of my sample apps:
todosForUser$ = this.http.get<User>(`${this.userUrl}/${this.userName}`)
.pipe(
switchMap(user =>
this.http.get<ToDo[]>(`${this.todoUrl}?userId=${user.id}`)
)
);
You can see this code here:
https://stackblitz.com/edit/angular-todos-deborahk
Using your code, it would be something like this (NOT syntax checked):
import { switchMap } from 'rxjs/operators';
this.globalCtrl.getSon()
.pipe(
switchMap(son => this.dashboardCtrl.getMarkers(son))
).subscribe(...);
UPDATE: Simplified initial example, which originally demonstrated how to handle multiple related datasets.
Upvotes: 2
Reputation: 8292
Your second subscription is put in a wrong place. It should be inside the response of a first subscription
this.globalCtrl.getSon().subscribe(
response => {
this.son= response;
// ADD THE OTHER SUBSCRIBE HERE
},
error => {
console.log(error);
}
The observable callback has 3 types - next
, error
, complete
You were putting the second subscription in a complete
callback and that was the reason it was never called (Your first observable never completed).
Read more about Observables here
Upvotes: 1
Reputation: 635
You have to move your second subscription inside your first one:
this.globalCtrl.getSon().subscribe(
response => {
this.son= response;
this.dashboardCtrl.getMarkers(this.son).subscribe(
response => {
this.markers = response["body"]["data"];
if (this.markers.length == 0) {
this.toast.fire({
type: "error",
title: "No hay datos geográficos del grupo seleccionado"
});
}
this.timezone = response["body"]["timezone"];
},
error => {
console.log(error);
}
},
error => {
console.log(error);
}
);
Upvotes: 1