1

I have home.ts which is calling service.ts to load items from Storage.

export class HomePage {

  products;

  ionViewDidEnter() {
    this.products = this.productService.products;
  }

  ngOnInit(){
      this.productService.fetchProducts();                                    
      this.products = this.productService.products;
  }
}

export class ProductService{ 

  products;

  fetchProducts(){    
    this.storage.get('products') // returns a promise which returns data or error    
      .then(
        (products) => {
        // assign to this.expenses only if not null. When first //strt, can be null. If null, assign empty array []
          products? this.products = products : this.products = [];                                            
          console.log("fetch Products:" + this.products);
          return this.products;
      })  
      .catch(
        err => console.log(err)
      );          
  }

I then render the items in home.html. The problem is, the items don't get displayed the first time round when the app starts. But if I navigate to another screen and return back to home.ts, the items get rendered back fine. I understand that this is because of ionViewDidEnter and perhaps the first time round, the promise in fetchProducts is asynchronous. But how do I get the items to list the first time round on ngOnInit?

eko
  • 39,722
  • 10
  • 72
  • 98
Jason
  • 1,059
  • 1
  • 13
  • 32
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – eko Apr 30 '17 at 15:42
  • Thanks for that. But what would be the specific code in my case? – Jason Apr 30 '17 at 15:49

2 Answers2

2

A way to handle your async issue is doing the operation inside the callback:

ngOnInit(){
      this.productService.fetchProducts()
        .then((res)=>{
          this.products = this.productService.products;
        });                              
}

You should also add a return statement here:

fetchProducts(){    
    return this.storage.get('products') // returns a promise which returns data or error    
      .then(..

Here's a plunker example: http://plnkr.co/edit/ONOg4FChJpCG81gM7Vlt?p=preview

eko
  • 39,722
  • 10
  • 72
  • 98
  • It would work for rendering home.ts, but products in productService would be undefined... – Jason Apr 30 '17 at 16:12
  • @Jason I've updated my answer but it shouldn't be undefined in the service also.. – eko Apr 30 '17 at 16:14
  • omg! It worked! And most importantly, I understand more about Promises and about asynchronous programming – Jason Apr 30 '17 at 16:22
0

As I see, you could do it in two different ways...

First modify the method so typescript understands that it returns a promise with a list of products:

fetchProducts(): Promise<Array<any>> {
  // ...
}

1) Preloading the information once: so you'll call the fetchProducts method only once (probably at startup) in order to load the products in memory, and then you'll use the products property to get the data

// In your app.component.ts
@Component({
    templateUrl: 'app.html'
})
export class MyApp {

    public rootPage: any; // Don't assign the page here yet

    constructor(private platform: Platform,
                private productService: ProductService) {
        this.platform.ready().then(() => {
            // ...

            this.productService.fetchProducts().then(() => {
                this.rootPage = HomePage;
            });
        });
    }

And then in the HomePage, since the data is already on memory, you can just use the products property from the service:

export class HomePage {

  products;

  ionViewDidEnter() {
    this.products = this.productService.products;
  }

}

2) Getting the products from the storage every time the user enters to the HomePage:

    export class HomePage {

      products;

      ionViewDidEnter() {
        this.productService.fetchProducts().then((products) => {
          this.products = this.productService.products;
        });   
      }

    }
sebaferreras
  • 44,206
  • 11
  • 116
  • 134