0

I want to create an array of objects with values retrieved in my firebase real time database.

For that, I use AngularFire library.

I have 4 functions that I use for return values into my array, but when I try to do it, all values are undefined.

This is my code :

getChats(){
    this.path = '/Users/' + this.uid;
    this.sub1 = this.CrudService.all(this.path + '/Chats').subscribe((chats:any) =>{
      if(chats.length){
        for(let i = 0; i < chats.length; i++){
          this.chats[i] = {};
          this.chats[i].chatID = chats[i].chatID;
          this.chats[i].contenderPicture = this.getContenderImg(chats[i].contenderID);
          this.chats[i].firstLetterName = this.getContenderNameTruncated(chats[i].contenderID);
          this.chats[i].lastMessage = this.getLastSentence(chats[i].chatID);
          this.chats[i].lastTime = this.getLastSentenceHour(chats[i].chatID);
        }
      }
    })
  }

  getContenderImg(contenderID:any){
    var path = '/Users/' + contenderID + '/profile_picture/0/url';
    this.sub1 = this.CrudService.read(path).subscribe(async picture => {
      await picture
      return picture
    });
  }

  getContenderNameTruncated(contenderID:any){
    var path = '/Users/' + contenderID + '/fname';
    this.sub2 = this.CrudService.read(path).subscribe((fname:any) => {
      var fnameLetter = fname.charAt(0);
      var truncated = fname.replace(/./gi, '*');
      var rmLastStar = truncated.slice(0, -1);
      var nameTruncated = fnameLetter + rmLastStar
      return nameTruncated
    });
  }

  getLastSentence(chatID:any){
    var path = '/Chats/' + chatID + '/lastMessage';
    this.sub3 = this.CrudService.read(path).subscribe((lastMessage:any) => {
      return lastMessage
    });
  }

  getLastSentenceHour(chatID:any){
    var path = '/Chats/' + chatID + '/lastTime';
    this.sub4 = this.CrudService.read(path).subscribe(lastTime => {
      return lastTime
    })
  }

As you can see, I've try to use async/await in the first function, but nothing change ...

Did I do something wrong ? I need your help, I am lost since 2 weeks now ...

Thank you all !

PS : "getChats()" function is called on init.

PalmThreeStudio
  • 489
  • 8
  • 21
  • Take a look at [this post](https://stackoverflow.com/q/43055706/1009922), and at [this other one](https://stackoverflow.com/q/14220321/1009922). – ConnorsFan Apr 29 '20 at 13:50
  • I can't figure how it can help me ... I've try to return a promise but it's not working ... Can you provide me a clear example please ? @ConnorsFan – PalmThreeStudio Apr 29 '20 at 14:18
  • 1
    The individual methods (`getContenderImg`, `getContenderNameTruncated`, etc.) should return their observable, and you should subscribe to them in `getChats`. You could use `forkJoin` to subscribe to all of them at once. – ConnorsFan Apr 29 '20 at 14:22
  • 1
    @ConnorsFan Please, create an answer because you just save my day, it's work ! I will mark your answer as correct one. – PalmThreeStudio Apr 29 '20 at 14:43

2 Answers2

0

One approach would be to promisify your subscription and handle the promises elegantly.

try the below approach. Its been cleaner this way than to handle too many Observables.

https://stackblitz.com/edit/angular-jgkvy5

import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  path = "";
  uid = "";
  chats: any[] = [];

  constructor(private CrudService: any) {}

  getChats() {
    this.path = "/Users/" + this.uid;

    this.CrudService.all(this.path + "/Chats")
    .toPromise()
    .then(async (chats: any) => {
      if (chats.length) {
        for (let i = 0; i < chats.length; i++) {
          this.chats[i] = {};

          this.chats[i].chatID = chats[i].chatID;

          this.chats[i].contenderPicture = await this.getContenderImg(chats[i].contenderID);
          this.chats[i].firstLetterName = await this.getContenderNameTruncated(chats[i].contenderID);
          this.chats[i].lastMessage = await this.getLastSentence(chats[i].chatID);
          this.chats[i].lastTime = await this.getLastSentenceHour(chats[i].chatID);
        }
      }
    });
  }

  getContenderImg(contenderID: any) {
    var path = "/Users/" + contenderID + "/profile_picture/0/url";
    return this.CrudService.read(path).toPromise().catch(()=>'');
  }

  getContenderNameTruncated(contenderID: any) {
    var path = "/Users/" + contenderID + "/fname";
    return this.CrudService.read(path).toPromise()
    .then((fname: any) => {
      let fnameLetter = fname.charAt(0);
      let truncated = fname.replace(/./gi, "*");
      let rmLastStar = truncated.slice(0, -1);
      let nameTruncated = fnameLetter + rmLastStar;
      return nameTruncated;
    })
    .catch(()=>'');
  }

  getLastSentence(chatID: any) {
    var path = "/Chats/" + chatID + "/lastMessage";
    return this.CrudService.read(path).toPromise().catch(()=>'');
  }

  getLastSentenceHour(chatID: any) {
    var path = "/Chats/" + chatID + "/lastTime";
    return this.CrudService.read(path).toPromise().catch(()=>'');
  }
}
blazehub
  • 1,880
  • 19
  • 25
-1
getChats(){
this.path = '/Users/' + this.uid;
this.sub1 = this.CrudService.all(this.path + '/Chats').subscribe((chats:any) =>{
  if(chats.length){
    for(let i = 0; i < chats.length; i++){
      this.chats[i] = {};
      this.chats[i].chatID = chats[i].chatID;
      forkJoin(
        this.getContenderImg(chats[i].contenderID),
        this.getContenderNameTruncated(chats[i].contenderID),
        this.getLastSentence(chats[i].chatID),
        this.getLastSentenceHour(chats[i].chatID)
      ).subscribe(res => {
          this.chats[i].contenderPicture = res[0];
          this.chats[i].firstLetterName = res[1];
          this.chats[i].lastMessage = res[2];
          this.chats[i].lastTime = res[3];
      })
    //   this.chats[i].contenderPicture = this.getContenderImg(chats[i].contenderID);
    //   this.chats[i].firstLetterName = this.getContenderNameTruncated(chats[i].contenderID);
    //   this.chats[i].lastMessage = this.getLastSentence(chats[i].chatID);
    //   this.chats[i].lastTime = this.getLastSentenceHour(chats[i].chatID);
    }
  }
})

}

  getContenderImg(contenderID:any){
var path = '/Users/' + contenderID + '/profile_picture/0/url';
var subject = new Subject<any>();
this.sub1 = this.CrudService.read(path).subscribe(picture => {
//   await picture
//   return picture
  subject.next(picture);
subject.complete();
});
return subject.asObservable();

}

  getContenderNameTruncated(contenderID:any){
var path = '/Users/' + contenderID + '/fname';
var subject = new Subject<any>();
this.sub2 = this.CrudService.read(path).subscribe((fname:any) => {
  var fnameLetter = fname.charAt(0);
  var truncated = fname.replace(/./gi, '*');
  var rmLastStar = truncated.slice(0, -1);
  var nameTruncated = fnameLetter + rmLastStar
//   return nameTruncated
    subject.next(nameTruncated);
    subject.complete();
});
return subject.asObservable();

}

  getLastSentence(chatID:any){
  var subject = new Subject<any>();
var path = '/Chats/' + chatID + '/lastMessage';
this.sub3 = this.CrudService.read(path).subscribe((lastMessage:any) => {
    // return lastMessage
     subject.next(lastMessage);
     subject.complete();
});
return subject.asObservable();

}

  getLastSentenceHour(chatID:any){
var subject = new Subject<any>();
var path = '/Chats/' + chatID + '/lastTime';
this.sub4 = this.CrudService.read(path).subscribe(lastTime => {
//   return lastTime
    subject.next(lastTime);
    subject.complete();

})
return subject.asObservable();

}

  • forkJoin, Subject needed to import from Rxjs. The idea is to return Observable from all child functions and subscrie all at once through forkJoin to get output of all child functions. – Subhojit Khara May 02 '20 at 15:28