Firestore 监听器订阅触发随机次数
Firestore listener subscription triggers random number of times
我有一个 Firestore 侦听器似乎触发了随机次数。在第一个页面加载时,它可能会触发 5 次,刷新页面并触发 13 次。
@Injectable({
providedIn: 'root',
})
export class AuthService {
user$: BehaviorSubject<SavedUser | undefined> = new BehaviorSubject<SavedUser | undefined>(undefined);
constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore, private router: Router) {
this.onAuthStateChanged();
}
onAuthStateChanged() {
let counter = 0;
this.angularFireAuth.authState.subscribe(user => {
if (user) {
this.firestore
.collection('user')
.doc<User>(user.uid)
.valueChanges()
.subscribe(userRecord => {
counter++
console.log(counter); // Testing
user.getIdToken(true);
this.user$.next(userRecord);
});
}
});
}
}
控制台日志的输出:
auth.service.ts:35 1
auth.service.ts:35 2
auth.service.ts:35 3
auth.service.ts:35 4
auth.service.ts:35 5
auth.service.ts:35 6
auth.service.ts:35 7
auth.service.ts:35 8
auth.service.ts:35 9
auth.service.ts:35 10
auth.service.ts:35 11
我在这里要做的就是在它支持的文档发生变化时刷新用户的令牌。
我知道 this.angularFireAuth.onAuthStateChanged(user => {...}
只触发了一次,文档没有发生任何变化。
我已经尝试通过 onDestroy
取消订阅 Firestore 订阅,但这没有任何区别。
作为“修复”,我认为我可以通过
读取第一个值并停止处理
this.firestore
.collection('user')
.doc<User>(user.uid)
.valueChanges()
.pipe(first())
.subscribe(userRecord => {...});
乍一看确实有效,但是当稍后更改文档时,这会阻止 .valueChanges()
触发。
有什么建议吗?
好吧,我已经解决了我的实际问题,方法是通过另一个 firestore 侦听器在对象上设置时间戳,然后比较当前和上一个以仅触发一次。
如果有人来这里做类似的事情,我会post这个代码,但我仍然想知道为什么我的订阅者经常关闭。
云函数:
export class UserUpdateListener {
public listen = functions.firestore
.document('user/{uid}')
.onWrite(async (snapshot) => {
const before: User = snapshot.before.data() as User;
const after: User = snapshot.after.data() as User;
const skipUpdate = before.lastUpdate && after.lastUpdate && !before.lastUpdate.isEqual(after.lastUpdate);
if (skipUpdate) {
functions.logger.info('No changes, skipping timestamp update');
return;
}
await snapshot.after.ref.update({ lastUpdate: admin.firestore.FieldValue.serverTimestamp() });
});
}
然后我使用以下方法检查客户端中的时间戳:
constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore, private router: Router) {
this.onAuthStateChanged();
let lastUpdate: Timestamp;
this.user$.subscribe(async (user) => {
if (this.authUser && user && user.lastUpdate) {
if (lastUpdate && !user.lastUpdate.isEqual(lastUpdate)) {
await this.authUser.getIdToken(true);
}
lastUpdate = user.lastUpdate;
}
});
}
希望这会节省一些时间。
我有一个 Firestore 侦听器似乎触发了随机次数。在第一个页面加载时,它可能会触发 5 次,刷新页面并触发 13 次。
@Injectable({
providedIn: 'root',
})
export class AuthService {
user$: BehaviorSubject<SavedUser | undefined> = new BehaviorSubject<SavedUser | undefined>(undefined);
constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore, private router: Router) {
this.onAuthStateChanged();
}
onAuthStateChanged() {
let counter = 0;
this.angularFireAuth.authState.subscribe(user => {
if (user) {
this.firestore
.collection('user')
.doc<User>(user.uid)
.valueChanges()
.subscribe(userRecord => {
counter++
console.log(counter); // Testing
user.getIdToken(true);
this.user$.next(userRecord);
});
}
});
}
}
控制台日志的输出:
auth.service.ts:35 1
auth.service.ts:35 2
auth.service.ts:35 3
auth.service.ts:35 4
auth.service.ts:35 5
auth.service.ts:35 6
auth.service.ts:35 7
auth.service.ts:35 8
auth.service.ts:35 9
auth.service.ts:35 10
auth.service.ts:35 11
我在这里要做的就是在它支持的文档发生变化时刷新用户的令牌。
我知道 this.angularFireAuth.onAuthStateChanged(user => {...}
只触发了一次,文档没有发生任何变化。
我已经尝试通过 onDestroy
取消订阅 Firestore 订阅,但这没有任何区别。
作为“修复”,我认为我可以通过
读取第一个值并停止处理this.firestore
.collection('user')
.doc<User>(user.uid)
.valueChanges()
.pipe(first())
.subscribe(userRecord => {...});
乍一看确实有效,但是当稍后更改文档时,这会阻止 .valueChanges()
触发。
有什么建议吗?
好吧,我已经解决了我的实际问题,方法是通过另一个 firestore 侦听器在对象上设置时间戳,然后比较当前和上一个以仅触发一次。
如果有人来这里做类似的事情,我会post这个代码,但我仍然想知道为什么我的订阅者经常关闭。
云函数:
export class UserUpdateListener {
public listen = functions.firestore
.document('user/{uid}')
.onWrite(async (snapshot) => {
const before: User = snapshot.before.data() as User;
const after: User = snapshot.after.data() as User;
const skipUpdate = before.lastUpdate && after.lastUpdate && !before.lastUpdate.isEqual(after.lastUpdate);
if (skipUpdate) {
functions.logger.info('No changes, skipping timestamp update');
return;
}
await snapshot.after.ref.update({ lastUpdate: admin.firestore.FieldValue.serverTimestamp() });
});
}
然后我使用以下方法检查客户端中的时间戳:
constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore, private router: Router) {
this.onAuthStateChanged();
let lastUpdate: Timestamp;
this.user$.subscribe(async (user) => {
if (this.authUser && user && user.lastUpdate) {
if (lastUpdate && !user.lastUpdate.isEqual(lastUpdate)) {
await this.authUser.getIdToken(true);
}
lastUpdate = user.lastUpdate;
}
});
}
希望这会节省一些时间。