0
getSpecificData(par) {
return this.afd.list('products/products', ref => ref.orderByChild('par').equalTo(par)).valueChanges();
}

In my components, i have this:

export class Product {
  name: string;
  price: string;
  quantity: string;
}

ionViewDidLoad() {
    let aux =this.readData();
    console.log('Products', aux);
}
readData() {
    return this.firebaseService.getSpecificData(this.par).subscribe(
        items => {
            this.data = items,
            console.log('Data from Firebase ', this.data)
        }
    );
}

The "console.log('Data from Firebase ', this.data)" is printing data right, but "console.log('Products', aux);" is getting me undefined.

What i am doing wrong?

My aim is to iterate the array of data and transform each item into an object of type product.

Regards,

ccorreia
  • 1
  • 1
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – trincot Jan 18 '18 at 16:02

2 Answers2

0

Your readData method doesn't return the actual records. Everything happens asynchronously, which is why it works within the subscribe handler (that bit only gets called when the asynchronous task has completed.

Quick timeline example:

  1. ionViewDidLoad()
  2. let aux = this.readData();
  3. readData()
  4. return this.firebaseService.getSpecificData(this.par).subscribe(
  5. );
  6. console.log('Products', aux); (TOO SOON!!!)
  7. (call to firebase getSpecificData completes)
  8. items => {
  9. this.data = items, This is the point where this.data receives the items
  10. console.log('Data from Firebase ', this.data)
  11. }
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • Thank you. I understood your explanation very well. But, this way, how can i transform the items into objects? It has to be asynchronous too? How to achieve it? – ccorreia Jan 18 '18 at 16:50
  • Yes, you have to work with the asynchronous action, effectively you need to trigger the use of the data inside your `subscribe` handler - you could call a method, or raise an event, or use the data in there. – Fenton Jan 18 '18 at 20:41
  • Ok. So if i use the data inside my subscribe it should be ok, right? Like this // readData() { return this.firebaseService.getSpecificData(this.par).subscribe( items => { this.data = items, this.Products.push(new Product(element[0], element[1], element[3])), console.log('Data from Firebase ', this.data) } ); }// But it didn't work :( – ccorreia Jan 19 '18 at 23:06
  • @ccorreia where did the `element` array come from... did you mean to use `this.data.element[0]` or similar? I assume the `console.log` bit works? – Fenton Jan 22 '18 at 21:16
  • Fenton, You led me to the solution. I discovered, a bit, how the asynchronous call works. I published the solution. If you have any advice to improve, please let me know. Thank you! – ccorreia Jan 23 '18 at 18:49
0

The explanation from Fenton is correctly.

I figure out the solution. Don't know yet if is the best solution, but it is working fine.

In my provider, i have the following code:

    export class Product {
    name: string;
    price: string;
    quantity: string;
    constructor(name: string, price: string, quantity: string) {
        this.name = name;
        this.price = name;
        this.quantity = quantity;
    }
}


    getSpecificData(par) {
    return this.afd.list('products/products', ref => ref.orderByChild('par').equalTo(par)).valueChanges().map(items => {
        let results = items.map(item => {
            return new Product(
                item.name,
                item.price,
                item.quantity
            );
        })
        return results;
    });
}

And im my component a have this:

readData() {
    this.firebaseService.getSpecificData(this.stock).map(
        data => {
            this.products = data;
        }
    ).subscribe();
}

It is working fine. I am reading the result in my html file.

<ion-col *ngFor=" let product of products" >
        {{product.name}}
</ion-col>
ccorreia
  • 1
  • 1