Reputation: 2371
I have an Ionic 2 app with a function that's aggregating a bunch of data via observables. The data comes back...except it's not always complete on the first return. After a few seconds, my data gets returned again, except both instances are now populated with the complete data. It's really weird and I'm not sure what's causing it.
Here is my function:
getUserStories(data) {
return this._af.database
.object(`/social/users/${data.id}`)
// Switch to the joined observable
.switchMap((user) => {
let connections = [];
let connectionKeys = Object.keys(user.connections);
return Observable.combineLatest(
connectionKeys.map((connectionKey) => this._af.database
.object(`/social/users/${connectionKey}`)
),
(...connections) => {
connectionKeys.forEach((connectionKey, index) => {
this._af.database
.object(`/social/user_stories_seen/${connectionKey}/${data.id}`).subscribe(data => {
// Iterate over the connections and append the correct "last_seen" variable
connections.forEach((connection, index) => {
if(connection.$key === connectionKey) {
connections[index]['last_seen'] = data;
}
})
});
})
return connections;
});
})
}
Here is the view that calls this functionality:
ionViewDidLoad() {
// Get the user from storage and get all the connections
this.storage.get('user').then(data => {
//Get the user profile
this._users.getUserStories({id: data.id}).subscribe(stories => {
console.log('stories', stories);
});
})
}
Has anyone else run into this issue?
Upvotes: 1
Views: 670
Reputation: 58410
The problem is that you have internal observables that are subscribing and then updating last_seen
properties of the connections.
Those observables are not are not composed into the observable you are returning, so they can emit and update the connections after your combineLatest
operator emits.
The implementation could be simplified by using a function that combines the connections and last-seen values:
getUserStories(data) {
return this._af.database
.object(`/social/users/${data.id}`)
.switchMap((user) => {
const getConnection = (connectionKey) => {
return Observable.combineLatest(
// Combine the connection and last-seen value:
this._af.database
.object(`/social/users/${connectionKey}`),
this._af.database
.object(`/social/user_stories_seen/${connectionKey}/${data.id}`),
// Assign the last-seen value, but return the connection:
(connection, seen) => {
connection.last_seen = seen;
return connection;
}
);
};
const connections = Object.keys(user.connections).map(getConnection);
return Observable.combineLatest(...connections);
});
}
Upvotes: 1