带有Firebase数据的Angular应用程序:为什么我看到上一页的数据



因此,我在Firebase上托管了一个Angular 9应用程序,并使用Firestore获取数据。我有一个问题看起来很简单,但我无法理解为什么会发生这种事。我已经对应用程序进行了大量简化,以找到问题的根本原因,并将在下面尽可能解释这个问题。

应用程序:我有两个页面,一个主页和一个交易页面。两个页面都是从同一个Firebase集合";交易";。然而,在主页上,我想显示最近的4笔交易(按日期降序排列(,而在交易页面上,我要显示最有利可图的10笔交易(按照金额降序排列(。目前,我只是将数据记录到控制台进行调试。在记录数据之前,我也会对其进行一些操作(请参阅下面的代码(。

问题:当我在主页上启动时,我可以在控制台中看到我最近的4笔交易。然而,当我转到Transactions页面时,它会在控制台中再次记录4个最新的事务,这些事务应该只显示在主页上。大约一秒钟后,它显示了预期的10笔最有利可图的交易。

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

txSubscription: Subscription;
constructor(
public afAuth: AngularFireAuth,
private readonly firestore: AngularFirestore
) { }
// Function to get the 4 most recent transactions
async getRecentTransactions() {
this.txSubscription = this.firestore
.collection('transactions', ref => ref.orderBy('date', 'desc').limit(4))
.valueChanges()
.subscribe(rows => {
this.recentTransactions = [];
rows.forEach(row => {
let jsonData = {};
jsonData['ticker'] = (row['ticker'].length <= 10 ? row['ticker'] : row['ticker'].substring(0, 10) + '...');
jsonData['date'] = formatDate(row['date'].toDate(), 'dd/MM/y', 'en');

jsonData['amount'] = prefix + formatNumber(row['netAmount'], 'be', '1.2-2');

this.recentTransactions.push(jsonData);
})
console.log("home page", this.recentTransactions);
})
}
ngOnInit() {
this.afAuth.onAuthStateChanged(() => {
this.getRecentTransactions();
})
}
ngOnDestroy() {
this.txSubscription.unsubscribe();
}

transaction.page.ts的代码非常相似:

txSubscription: Subscription;
constructor(
public afAuth: AngularFireAuth,
private readonly firestore: AngularFirestore
) { }
// Function to load the data for the home page
loadHomeData() {
this.txSubscription = this.firestore
.collection('transactions', ref => ref.orderBy('profitEur', 'desc').limit(10))
.valueChanges()
.subscribe(rows => {
this.resultRows = [];
rows.forEach(row => {
this.resultRows.push(row['ticker'].slice(0, 8));
});
console.log("transaction page", this.resultRows);
})
}
ngOnInit() {
this.afAuth.onAuthStateChanged(() => {
this.loadHomeData();
})
}
ngOnDestroy() {
this.txSubscription.unsubscribe();
}

结果:以下是每一步输出到控制台的内容

  1. 我在主页上打开应用程序(如预期的那样有4行(:
home page (4) [{…}, {…}, {…}, {…}]
0: {ticker: "BAR", date: "21/07/2020", amount: "- € 1 086,10"}
1: {ticker: "ASL C340.0...", date: "18/07/2020", amount: "€ 0,00"}
2: {ticker: "ASL C340.0...", date: "14/07/2020", amount: "- € 750,85"}
3: {ticker: "TUI C7.00 ...", date: "20/06/2020", amount: "€ 0,00"}
length: 4
__proto__: Array(0)
  1. 我导航到交易页面:
transaction page (4) ["TUI C7.0", "ASL C340", "BAR", "ASL C340"]
transaction page (10) ["ASL C240", "ASL C232", "REC", "ASL C270", "ASL C310", "ASML", "ASL P220", "BAR", "CFEB", "MELE"]

为什么在导航到主页时,它会在控制台中再次显示主页中相同的4行

您在事务页面上得到两次结果。valueChanges很可能从内存缓存中的firestore返回数据作为快速响应,然后从实际数据中读取。在您的案例中,4行在返回到主页时被缓存,它们是从事务页面的缓存中处理的。

我认为问题在于:

loadHomeData() {
this.txSubscription = this.firestore
...
.subscribe(rows => {
...
})
}
ngOnInit() {
this.afAuth.onAuthStateChanged(() => {
this.loadHomeData();
})
}
ngOnDestroy() {
this.txSubscription.unsubscribe();
}

您取消订阅是正确的。但是,看看当onAuthStateChanged再次触发时会发生什么。您的第一个订阅已丢失,无法取消订阅。我认为在onAuthStateChanged上使用switchmap运算符可以解决您的问题。类似这样的东西:

this.subscription = this.af.authState.pipe(
switchMap(auth => {
if(auth !== null && auth !== undefined){
return   this.firestore.collection('transactions', ref => ref.orderBy('profitEur', 'desc').limit(10)).valueChanges())
} else{
throw "Not loggedin";
}
).subscribe(...)

发生此问题可能是因为

this.afAuth.onAuthStateChanged()

被触发两次。

而不是检查每个组件的身份验证状态。您可以简单地在app.component.ts订阅身份验证状态。如果用户未经身份验证或身份验证状态发生更改,它将重定向到登录页面,否则将重定向到home.page.ts

export class AppComponent {
constructor(private readonly auth: AngularFireAuth, private router: Router) {
this.auth.authState.subscribe(response => {
console.log(response);
if (response && response.uid) {
this.router.navigate(['dashboard', 'home']); //Home page route
} else {
this.router.navigate(['auth', 'login']); //Login page route
}
}, error => {
this.auth.signOut();
this.router.navigate(['auth', 'login']); //Login Page route
});
}
}

在你的家里;transaction.page.ts无需检查身份验证状态。

  • 主页组件.ts
txSubscription: Subscription;
constructor(
public afAuth: AngularFireAuth,
private readonly firestore: AngularFirestore
) { }
// Function to get the 4 most recent transactions
async getRecentTransactions() {
this.txSubscription = this.firestore
.collection('transactions', ref => ref.orderBy('date', 'desc').limit(4))
.valueChanges()
.subscribe(rows => {
this.recentTransactions = [];
rows.forEach(row => {
let jsonData = {};
jsonData['ticker'] = (row['ticker'].length <= 10 ? row['ticker'] : row['ticker'].substring(0, 10) + '...');
jsonData['date'] = formatDate(row['date'].toDate(), 'dd/MM/y', 'en');

jsonData['amount'] = prefix + formatNumber(row['netAmount'], 'be', '1.2-2');

this.recentTransactions.push(jsonData);
})
console.log("home page", this.recentTransactions);
})
}
ngOnInit() {
this.getRecentTransactions();
}
ngOnDestroy() {
this.txSubscription.unsubscribe();
}
  • 交易页面.ts
txSubscription: Subscription;
constructor(
public afAuth: AngularFireAuth,
private readonly firestore: AngularFirestore
) { }
// Function to load the data for the home page
loadHomeData() {
this.txSubscription = this.firestore
.collection('transactions', ref => ref.orderBy('profitEur', 'desc').limit(10))
.valueChanges()
.subscribe(rows => {
this.resultRows = [];
rows.forEach(row => {
this.resultRows.push(row['ticker'].slice(0, 8));
});
console.log("transaction page", this.resultRows);
})
}
ngOnInit() {
this.loadHomeData();
}
ngOnDestroy() {
this.txSubscription.unsubscribe();
}

相关内容

  • 没有找到相关文章

最新更新