Background
I am currently making a find function for a messaging app, where each collection of messages is referenced by an index. When find()
is invoked, it has to extract each message collection reference from the messageRef
variable, then use getMessageCollectionFromRef(id)
to get the Observable for the message collection. Then, it must grab the user id
from this Observable's subscribed JSON data of the person who is not the user, and then invoke getUserById(id)
to get the Observable for the user info. Lastly, it must compare the name of the retrieved user to the value of the ngModel
search
. If search
is a substring of userJSONData
, then the messageRef
of the message collection must be put into the messages
Observable, from which async
data is loaded on the Angular front-end.
Note: Function cancelFind()
is called at the beginning of the find()
function only to revert the message Observable list to its original length from AngularFire2 data. This works well.
Attempt
find():void {
this.cancelFind();
console.log("- find Started -");
var newMessages = new Array();
this.messages = this.messages.switchMap((messages) => {
console.log("Got messages: " + JSON.stringify(messages));
messages.forEach((msg) => {
console.log("Iterating through message #" + msg.$value);
this.msgClass.getMessageCollectionFromRef(msg.$value).take(1).subscribe((message) => {
var id = (message.messager1.id != this.user.id ? message.messager1.id : message.messager2.id)
this.userClass. getUserById(id).take(1).subscribe((messager) => {
if (messager.name.includes(this.search)) {
console.log("Pushing " + JSON.stringify(msg) + " to list");
newMessages.push(msg);
}
});
});
});
console.log("Found list: " + JSON.stringify(newMessages));
return Observable.forkJoin(newMessages);
});
console.log("- find Resolved -");
}
Output
[08:41:59] console.log: - find Started -
[08:41:59] console.log: Got messages: [{"$value":0},{"$value":1}]
[08:41:59] console.log: - find Resolved -
[08:41:59] console.log: Iterating through message #0
[08:41:59] console.log: Iterating through message #1
[08:41:59] console.log: Found list: []
[08:41:59] console.log: Pushing {"$value":0} to list
Side note: Yes, I know my - find Started -
and - find Resolved -
logs follow synchronous conventions. This is standard in the app I'm developing and would not like to stray away from this.
Error
I am not getting an error, but my issue is that the messages
Observable remains empty and, consequently, no message collections appear on screen.
This problem is very unique in that it concerns retrieving nested Observable values in a loop, and I have not found adequate solutions to this issue online. The only similar solutions, such as that to a question I asked months ago found here, concern creating an Observable array off of synchronously-retrieved data.
I apologize for the adequately large description in relation to the length of code, but I believe there is an easy fix for this that I was not able to pinpoint for days. I am still new to Observables, so I will appreciate any help you can provide. Thank you so much!
CozyAzure's Solution
Following CozyAzure's solution, I have been able to produce a newly searched Observable array with properly added values. However, instead of omitting non-matches (null
values), the filter
command does not do anything to the result Observable array. Here is my resulting error:
Workaround
Check for null in your front-end as the async
pipe loads messages.
<div *ngFor="let msg of messages | async">
<message-card *ngIf="msg" [ref]="msg" ></message-card>
</div>