【问题标题】:Ionic app start working before initialization is finished离子应用程序在初始化完成之前开始工作
【发布时间】:2023-03-09 04:03:02
【问题描述】:

我正在使用Firebase Realtime DB 开发一个Ionic 条形码扫描仪应用程序。 在启动时,应用程序应该从Firebase 同步数据。但不知何故,该应用程序似乎在初始化/与数据库同步完成之前开始工作。因此用户不会看到任何数据。

在几次重启后,应用完成了数据同步,用户终于可以看到数据了。 请指导我解决此问题。每次用户使用该应用时,该应用都会同步数据?

提前致谢!

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);
      });
  }
}


【问题讨论】:

  • 作为 UI 注释,您希望某些内容显示在屏幕上,即使它不是数据,因为仍在获取数据、微调器、进度条等。并且选项卡正在加载,然后要求数据,所以总会有延迟。如果您只显示几秒钟的空白屏幕,研究表明用户会很快放弃您的应用。
  • 您好,感谢您的评论。我明白你的意思了。但问题是,该应用程序将开始运行,并且尚未获取一些数据,并且不幸的是之后也不会同步。只有在应用程序重新启动几次后,整个数据才被加载。
  • 标签页是起始页吗?您可以将对服务的调用移动到 app.component 中,这样它就可以更早地开始。数据的获取会受到随机因素的影响,所以你永远不能假设它总是以一定的速度加载。之后的同步听起来是一个不同的(也是更重要的)问题。
  • 嗨史蒂夫,再次感谢您的回答。我试图在 app.componet 文件中调用该服务,但不幸的是它不起作用。登录后,产品数据似乎以某种方式未同步。与其他数据相同,例如个人资料数据等。
  • 您可以使用角度生命周期事件和离子页面生命周期事件,例如ngAfterViewInitsionViewDidEnter

标签: javascript angular firebase ionic-framework firebase-realtime-database


【解决方案1】:

看起来您粘贴了两次 Tabs 组件而不是数据服务,但如果您的目标是让它等待,那么在我看来您只是没有在异步函数上添加等待,例如:

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

话虽如此,正如某些 cmets 中所提到的,这可能不是最佳做法,为了提供更好的用户体验,您应该允许异步函数“同步”工作、加载页面并显示用户一个微调器或一些反馈,以表明数据库仍在获取数据,直到数据从数据库返回。

【讨论】:

    【解决方案2】:

    我终于用这个解决方案解决了这个问题:https://forum.ionicframework.com/t/how-to-reload-page-every-time-click-on-tabs/115947/4

    非常感谢你们的帮助! :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 2019-01-18
      相关资源
      最近更新 更多