1

I use a loop to retrieve the data stored in Firebase thanks to the subscribe function and forEach. When I do a console.log of my datas in the subscribe ("=== SUBSCRIBE ===") I have the good result, but when I do a console.log outside ("=== HOME ===" and "=== RETURN ==="), I have this result :

screen of console.log

I suppose it comes from the fact that it is asynchronous, how to fix this problem please ?

This is my code :

statut: FirebaseListObservable<any[]>;
  statuts: Array<any> = [];

  // Données à enregistrer dans FireBase
  dateOfTheDay: string;
  dayOfWeek: number;

  constructor(public afDB: AngularFireDatabase, public storage: Storage) {
    moment.locale('fr');
    this.dateOfTheDay = moment().format('L'); // Date au format : 04/07/2017
    this.dayOfWeek = moment().day(); // Numéro du jour de la semaine (Ex : 1 pour lundi)
    this.statut = this.afDB.list('/statut');
  }

  statusToShow() {
    this.statut.subscribe(statut => {
      statut.forEach(s => {
        if (this.dateOfTheDay === s.statut_date_tache) {
          if (s.statut_id_tache in this.statuts === false) {
            this.statuts[s.statut_id_tache] = s;
          }
        }
      });

      console.log('=== SUBSCRIBE ===');
      console.log(this.statuts);
    });

    console.log('=== RETURN ===');
    console.log(this.statuts);

    return this.statuts;
  }

Thanks in advance

Swapnil Patwa
  • 4,069
  • 3
  • 25
  • 37
Valentin Harrang
  • 1,081
  • 2
  • 17
  • 34
  • Not sure. Once make sure `this` referes to the current class or not outside the `subscribe`. – Sai M. Jul 25 '17 at 14:09

2 Answers2

1

Comment: This is borderline exact duplicate, but the latter part of question is not, therefore an answer.

You are correct with the assumption that this is asynchronous, and as presented here How do I return the response from an Observable/http/async call in angular2? you need to handle everything inside the callback (subscribe). BUT, here you want to return the response. You cannot do that, as said here: https://stackoverflow.com/a/39296015 it is not possible from subscribe.

What you can do, like presented in answer, you can use map and then return an observable, that you can subscribe to or use the async pipe if you want to use it in view.

Call the statusToShow() in the service from the component where you need it and subscribe to the value:

Service:

statusToShow() {
  return this.afDB.list('/statut').map(statut => {
    for(let s of statut) {
      if (this.dateOfTheDay === s.statut_date_tache) {
        if (s.statut_id_tache in this.statuts === false) {
          return localStatuts[s.statut_id_tache] = s;
        }
      }
    }
    // return something else if value is not found above
  });
}

Then you can subscribe to this observable in the component and you get the statut value:

Component:

constructor(private service: TodolistService) { }

ngOnInit() {
  this.service.statusToShow()
    .subscribe(statut => this.statut = statut)
}

I suggest you check the official http-tutorial. I know that you are using Firebase, but the idea is the same :)

AT82
  • 71,416
  • 24
  • 140
  • 167
  • Thank you, I try this. Where do I put the subscription ? – Valentin Harrang Jul 25 '17 at 15:20
  • Replace it with `this.statut = this.afDB.list('/statut');` :) – AT82 Jul 25 '17 at 15:22
  • I have my todolistService (Where is my statusToShow() function) and home.ts where I would like to retrieve my datas – Valentin Harrang Jul 25 '17 at 15:24
  • Sorry, I don't understand what you mean :) Do you wonder about where to put this `return this.statut.map....` code or am I completely misunderstanding? – AT82 Jul 25 '17 at 15:26
  • My service : https://pastebin.com/VDr13WpY, it's good ? And I would like to get my datas in my home.ts – Valentin Harrang Jul 25 '17 at 15:30
  • Aaah, this is a **service** do not make requests in constructor of service. You can never know how long it will take. You should call methods from component, service makes the request and return the response to the component, where you subscribe. – AT82 Jul 25 '17 at 15:32
  • I do not know how to do this :( it's possible to make a pastebin please ? – Valentin Harrang Jul 25 '17 at 15:36
  • Updated my answer a bit, that should help :) – AT82 Jul 25 '17 at 15:52
  • home.ts : https://pastebin.com/eW4dbp0B / Service : https://pastebin.com/KkKRDyzq like this ? :) – Valentin Harrang Jul 25 '17 at 16:49
  • That looks pretty correct yes :) Are you having some problem with the code? – AT82 Jul 25 '17 at 16:51
  • I have no error :) but how do I access my values ? – Valentin Harrang Jul 25 '17 at 16:55
  • Well you have the value in `this.statusOfTheDay` in component, yes? or what do you mean by **access my values**? – AT82 Jul 25 '17 at 16:56
  • Yes and when I make a console.log(this.statusOfTheDay), there is an array but it is empty :/ – Valentin Harrang Jul 25 '17 at 17:12
  • okay, well you need to debug your code and see why that is. Are you getting any data from db... and if so, check step by step where the data is "disappearing" – AT82 Jul 25 '17 at 17:54
  • Okay, thank you very much for your help ! – Valentin Harrang Jul 25 '17 at 18:15
  • It is on the home.ts side that there must be a problem because I do not get my data in the array. What the function returns is correct, but not in the home.ts side – Valentin Harrang Jul 26 '17 at 07:47
  • I see error now. You need to have some value in `this.statuts`. So whatever that is, you need to first fetch that data. the problem is in this line: if `(s.statut_id_tache in this.statuts === false) {` I don't know what that is in your code, but the error is there. – AT82 Jul 26 '17 at 11:14
  • I asked a new question and it's solved :) thank you very much ! https://stackoverflow.com/questions/45322698/retrieve-data-from-an-asynchronous-service-in-a-component/45323468?noredirect=1#comment77609793_45323468 – Valentin Harrang Jul 26 '17 at 11:34
0

Problem here is, that this.statut.subscribe(statut => {}) is a asyncronous function.

Your console.log()s outside this function has already been executed while the subscribe callback wasn't finished. You could do this:

statusToShow() {

let localStatuts: Array<any>

this.statut.subscribe(statut => {
  statut.forEach(s => {
    if (this.dateOfTheDay === s.statut_date_tache) {
      if (s.statut_id_tache in this.statuts === false) {
        localStatuts[s.statut_id_tache] = s;
      }
    }
  });

  console.log('=== SUBSCRIBE ===');
  console.log(localStatuts);

  this.statuts = localStatuts;
  return localStatuts;

  });
}
Ma Kobi
  • 888
  • 6
  • 21