【问题标题】:Angular/Firebase app keeps showing data from previous pageAngular/Firebase 应用程序不断显示上一页的数据
【发布时间】:2020-11-27 03:30:40
【问题描述】:

我有一个带有主页的 Angular 应用程序,其中显示了“事务”Firebase 集合中的 4 个最新行(按日期排序,降序排列)。然后有一个单独的交易页面,我在其中显示了该集合中的前 10 行(按金额排序,降序)。但是,当我从主页开始然后转到交易页面时,在我的条形图中应该按金额显示前 10 笔交易,我仍然看到主页上最近的 4 笔交易。

演示链接: https://tickrs-app.web.app/

重现步骤:

  1. 打开演示应用
  2. 在主页最底部,您会看到“最近的交易”
  3. 打开菜单并导航到“交易”页面
  4. 条形图看起来有点奇怪,数据似乎仍然包含首页最近的 4 笔交易
  5. 导航到其他页面(不是主页),然后返回“交易”页面,条形图现在应该看起来正常

这是我的 home.page.ts 代码:

  // Function to load the 4 most recent transactions to show on the home page
  async loadData() {
    // Order by date, descending
    const orderParamsDateDesc = {
      field: 'date',
      order: 'desc'
    }
    
    // Call our service to load the data, given the ordering details, and limit the number of rows to 4
    await this._FirebaseService.readSortLimit('transactions', orderParamsDateDesc, 4).then(result => this.transactionRows = result);
  }

  async ngOnInit() {
    // Only try to load the data if the user is authenticated again
    this.afAuth.onAuthStateChanged(async () => {
      await this.loadData();
    })
  }

以下是 transaction.page.ts 的相同代码:

  // Function to load the top 10 transactions, ordered by amount (descending)
  async getRows() {
    // Initialize the arrays
    this.barChartDataEur = [];
    this.barChartLabelsEur = [];
    let rows: any = [];

    // Order by amount, descending
    let orderParams = {
      field: 'amount',
      order: 'desc'
    }

    // Call our service to load the data given the ordering details, and limit the number of rows to 10
    await this._FirebaseService.readSortLimit("transactions", orderParams, 10).then(result => rows = result);

    // Loop over the resulting rows and load the stock tickers and amount separately in the arrays which will be used for the bar chart
    await rows.forEach(row => {
      this.barChartLabelsEur.push(row.ticker.slice(0, 8));
      this.barChartDataEur.push(row.amount);
    });

    // Set the loaded flag to true
    this.loaded = true;
  }

  ngOnInit() {
    // Only execute this part if user is authenticated
    this.afAuth.onAuthStateChanged(async () => {
      this.getRows();
    })
  }

这是 transaction.page.html 的一部分,用于呈现条形图:

  <div class="chart-canvas">
    <canvas baseChart *ngIf="loaded"  // Only if data is loaded
            [data]="barChartDataEur"
            [labels]="barChartLabelsEur"
            [chartType]="barChartType"
            [options]="barChartOptions"
            [colors]="barChartColors"
            [legend]="barChartLegend"
            [plugins]="barChartPlugins">
    </canvas>
  </div>

这是我的 firebase.service.ts 以及在两个页面上都使用的 readSortLimit 函数:

  // Input: name of the Firebase collection, the ordering details and the number of rows to return
  readSortLimit(collection, orderDetails, limitNumber) {
    return new Promise((resolve, reject) => {
      let result = [];
      this.firestore
        .collection(collection, ref => ref
          .orderBy(orderDetails.field, orderDetails.order)
          .limit(limitNumber)
        )
        .snapshotChanges()
        .subscribe(item => {
          Array.from(item).forEach(row => {
            result.push(row.payload.doc.data());
          });
          resolve(result);
        });
    });
  }

【问题讨论】:

  • 我使用 Angularfire 来获取页面数据,所以我对使用 Firebase 原生函数不是很熟悉。但是,当新记录发生更改时,您可能不会在 Firebase 中看到它们。 resolve(result); 是不是没有完成承诺,所以你的数据已经加载,但你还没有监听 observable 的变化?
  • 嘿,我实际上也在使用@angular/fire。我不确定发生了什么 - 在主页上,我从我的收藏中读取了前 4 行,这很好。然后,然而,在下一页而不是前 4 名,我想要前 10 名。而不是获得前 10 名,我仍然从主页看到相同的 4 以及从 Firestore 读取的前 10 名......跨度>
  • 看来您正在将数据放入一个数组中,因此您将第二页上的 10 添加到第一页的原始 4 中。为什么不简单地继续返回集合并使用异步管道?
  • 嗨@StevenScott,我已经编辑了我的帖子,提供了更多细节,还添加了我的应用程序的演示链接,以便更好地了解这个问题。基本上,在这两个页面上,我都需要显示一个单独的数据集。两者都来自 Firebase 中的“交易”集合,但主页上的一个按日期排序,而交易页面上的一个按金额排序。
  • 有趣。我明白你的意思了。当我最初切换时,值只有 4 条记录,而不是 14 条。我切换到表视图以更好地理解数据。当我在页面中移动时,它会正确刷新。菜单上的重新加载也将其转换为 10 个条目。我与您使用的唯一区别(尽管我使用 Firebase 实时数据库)是在处理项目列表时使用 ValueChanges() 而不是 SnapshotChanges()。

标签: javascript angular firebase google-cloud-firestore angularfire


【解决方案1】:

snapshotChanges 可能会首先处理并从缓存中返回数据作为快速结果。您的函数readSortLimit 返回一个promise,并且promise 由缓存中的数据解析。下一个resolves 将被忽略。

您需要修改函数readSortLimit 以改为返回Observable

  readSortLimit(collection, orderDetails, limitNumber) {
    return this.firestore
        .collection(collection, ref => ref
          .orderBy(orderDetails.field, orderDetails.order)
          .limit(limitNumber)
        )
        .snapshotChanges()
        .subscribe(items => {
          Array.from(items).map(row => row.payload.doc.data()));
        });
  }

然后修改getRows

  async getRows() {
    // Order by amount, descending
    let orderParams = {
      field: 'amount',
      order: 'desc'
    }

    // Call our service to load the data given the ordering details, and limit the number of rows to 10
    this._FirebaseService.readSortLimit("transactions", orderParams, 10)
           .subscribe(rows => {
             // Initialize the arrays
             this.barChartDataEur = [];
             this.barChartLabelsEur = [];

             // Loop over the resulting rows and load the stock tickers and amount separately in the arrays which will be used for the bar chart
             rows.forEach(row => {
               this.barChartLabelsEur.push(row.ticker.slice(0, 8));
               this.barChartDataEur.push(row.amount);
             }); 
             
             // Set the loaded flag to true
             this.loaded = true;            
           });
  }

**确保getRows 最多调用一次。否则你会多次订阅同一个事件。

【讨论】:

    猜你喜欢
    • 2015-08-27
    • 2020-06-28
    • 2016-10-28
    • 2020-12-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多