vlntn
vlntn

Reputation: 370

Ionic app start working before initialization is finished

I am developing an Ionic Barcode Scanner App with Firebase Realtime DB. On the startup, the app should sync the data from Firebase. But somehow it seems like the app starts to work before the initialization / sync with the DB is completed. Hence the user will not see any data.

After a couple of restarts, the app finished to sync the data and the user can finally see the data. Kindly guide me to fix this issue. That the app will sync the data every time the user uses the app?

Thanks in advance!

tabs.page.ts

import { Component, OnInit } from '@angular/core';
import { BarcodeScanner } from '@ionic-native/barcode-scanner/ngx';
import { DataServiceService } from '../../app/data-service.service';
import { Toast } from '@ionic-native/toast/ngx';
import { Platform, AlertController } from '@ionic/angular';
import * as moment from 'moment';
@Component({
  selector: 'app-tabs',
  templateUrl: './tabs.page.html',
  styleUrls: ['./tabs.page.scss'],
})
export class TabsPage implements OnInit {

  productViews: any = {};
  productViewsbyUser: any[] = [];
  isProdcutsAvailable = true;

  selectedProduct: any;
  isCameraOpen = false;
  showScan = false;
  products: any[] = [];
  productFound = true;
  displayUserName: any;

  exitModalDisplayed = false;


  constructor(
    private barcodeScanner: BarcodeScanner,
    private toast: Toast,
    public platform: Platform,
    public dataService: DataServiceService,
    public alertCtrl: AlertController) {
    console.log(`Tabs Page called`);
    }

  ngOnInit() {

    this.productHunt();

  }

  productHunt() {
    this.dataService.getProducts()
    .subscribe((response) => {
      this.products = <any[]><unknown>response;
      console.table('products ', this.products);
     });
  }

  getMoment() {
    return moment().milliseconds(0);
  }

// Start scanning procedure
  scan() {
    this.selectedProduct = {};
    this.isCameraOpen = true;
    this.showScan = true;
    this.barcodeScanner.scan().then((barcodeData) => {
      setTimeout(() => {
        this.isCameraOpen = false;
      }, 500);
      if (barcodeData.cancelled) {
        return;
      }
      console.log(`barcodeData`, barcodeData);
      this.selectedProduct = this.products.find(product => product.prodId === barcodeData.text);
      if (this.selectedProduct !== undefined) {
        this.selectedProduct.scannedAt = this.getMoment().toISOString();
        // this.selectedProduct.userName = this.displayUserName(); // TO TEST !!!
        this.productFound = true;
        // insert product views with firebase generated based key
        this.dataService.insertProductViewAnalytics(this.selectedProduct)
          .subscribe(() => {
            console.log(`Product view analytics inserted in Firebase`);
            this.initScanHistoryData();
          });
      } else {
        this.productFound = false;
        this.toast.show(`Product not found`, '5000', 'center').subscribe(
          toast => {
            console.log(toast);
          }
        );
      }
    }, (err) => {
      setTimeout(() => {
        this.isCameraOpen = false;
      }, 1000);
      this.toast.show(err, '5000', 'center').subscribe(
        toast => {
          console.log(toast);
        }
      );
    });
  }

  async initScanHistoryData() {
    this.dataService.getProductViewsForUser()
      .subscribe((response) => {
        this.productViews = response;
        const userProductViews = [];
        // tslint:disable-next-line: forin
        for (const key in this.productViews) {
          userProductViews.push(this.productViews[key]);
        }
          userProductViews.sort(function (a, b) {
            return moment(b.scannedAt).diff(moment(a.scannedAt));

            // ENTER USER NAME HERE???

        });

        this.productViewsbyUser = userProductViews;
        console.log('user productViews ', userProductViews);

        if (this.productViewsbyUser.length) {
          this.isProdcutsAvailable = true;
        } else {
          this.isProdcutsAvailable = false;
        }
        console.log('productViews ', this.productViews);
      });
  }
}


data-service.service.ts

import { Component, OnInit } from '@angular/core';
import { BarcodeScanner } from '@ionic-native/barcode-scanner/ngx';
import { DataServiceService } from '../../app/data-service.service';
import { Toast } from '@ionic-native/toast/ngx';
import { Platform, AlertController } from '@ionic/angular';
import * as moment from 'moment';
@Component({
  selector: 'app-tabs',
  templateUrl: './tabs.page.html',
  styleUrls: ['./tabs.page.scss'],
})
export class TabsPage implements OnInit {

  productViews: any = {};
  productViewsbyUser: any[] = [];
  isProdcutsAvailable = true;

  selectedProduct: any;
  isCameraOpen = false;
  showScan = false;
  products: any[] = [];
  productFound = true;
  displayUserName: any;

  exitModalDisplayed = false;


  constructor(
    private barcodeScanner: BarcodeScanner,
    private toast: Toast,
    public platform: Platform,
    public dataService: DataServiceService,
    public alertCtrl: AlertController) {
    console.log(`Tabs Page called`);
    }

  ngOnInit() {

    this.productHunt();

  }

  productHunt() {
    this.dataService.getProducts()
    .subscribe((response) => {
      this.products = <any[]><unknown>response;
      console.table('products ', this.products);
     });
  }

  getMoment() {
    return moment().milliseconds(0);
  }

// Start scanning procedure
  scan() {
    this.selectedProduct = {};
    this.isCameraOpen = true;
    this.showScan = true;
    this.barcodeScanner.scan().then((barcodeData) => {
      setTimeout(() => {
        this.isCameraOpen = false;
      }, 500);
      if (barcodeData.cancelled) {
        return;
      }
      console.log(`barcodeData`, barcodeData);
      this.selectedProduct = this.products.find(product => product.prodId === barcodeData.text);
      if (this.selectedProduct !== undefined) {
        this.selectedProduct.scannedAt = this.getMoment().toISOString();
        // this.selectedProduct.userName = this.displayUserName(); // TO TEST !!!
        this.productFound = true;
        // insert product views with firebase generated based key
        this.dataService.insertProductViewAnalytics(this.selectedProduct)
          .subscribe(() => {
            console.log(`Product view analytics inserted in Firebase`);
            this.initScanHistoryData();
          });
      } else {
        this.productFound = false;
        this.toast.show(`Product not found`, '5000', 'center').subscribe(
          toast => {
            console.log(toast);
          }
        );
      }
    }, (err) => {
      setTimeout(() => {
        this.isCameraOpen = false;
      }, 1000);
      this.toast.show(err, '5000', 'center').subscribe(
        toast => {
          console.log(toast);
        }
      );
    });
  }

  async initScanHistoryData() {
    this.dataService.getProductViewsForUser()
      .subscribe((response) => {
        this.productViews = response;
        const userProductViews = [];
        // tslint:disable-next-line: forin
        for (const key in this.productViews) {
          userProductViews.push(this.productViews[key]);
        }
          userProductViews.sort(function (a, b) {
            return moment(b.scannedAt).diff(moment(a.scannedAt));

            // ENTER USER NAME HERE???

        });

        this.productViewsbyUser = userProductViews;
        console.log('user productViews ', userProductViews);

        if (this.productViewsbyUser.length) {
          this.isProdcutsAvailable = true;
        } else {
          this.isProdcutsAvailable = false;
        }
        console.log('productViews ', this.productViews);
      });
  }
}


Upvotes: 0

Views: 563

Answers (2)

vlntn
vlntn

Reputation: 370

I finally used this solution to fix the issue: https://forum.ionicframework.com/t/how-to-reload-page-every-time-click-on-tabs/115947/4

Thanks a lot for your help guys! :)

Upvotes: 0

MapLion
MapLion

Reputation: 1131

It looks like you pasted your Tabs component twice instead of your data service, but if your goal is to make it wait then it looks to me like you're just not adding awaits on your async functions, for example:

async initScanHistoryData() {
    await this.dataService.getProductViewsForUser()
    ...
}

That being said, as mentioned in some of the comments, this is probably not the best of practices and to give a better user experience, you should allow your asynchronous function to work "synchronously", have the page load, and show the user a spinner or some feedback to show that the database is still fetching until the data comes back from the database.

Upvotes: 1

Related Questions