使用 firebase 和 angular 的无限循环
Infinit loop with firebase and angular
我在使用 firebase 保存数据时遇到无限循环问题
this.db.collection('users').doc(this.useruid).update({Info: this.currentInfo})
private currentInfo:string[];
private useruid: string;
...
constructor(private AngularAuth: AngularFireAuth,
private db:AngularFirestore) { }
...
sendInfo(text:string){
this.useruid = this.AngularAuth.auth.currentUser.uid;
this.db.collection('users').doc(this.useruid).snapshotChanges().subscribe(a=>{
const data = a.payload.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
this.db.collection('users').doc(this.useruid).update({
Info: this.currentInfo
})...
})
}
举个例子,假设我目前有 currentInfo = ["a","b","c"]
和 text = "d"
,在 y 运行 方法 sendInfo( )
之后,
我得到一个循环:["a","b","c","d","a","b","c","d","d","a","b","c","d","a","b","c","d","d","d"...]
等等。
要根据文档的当前值更新文档,use a transaction:
var userDocRef = collection('users').doc(this.useruid);
return db.runTransaction(function(transaction) {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(userDocRef).then(function(userDoc) {
if (!userDoc.exists) {
throw "Document does not exist!";
}
const data = userDoc.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
transaction.update(userDocRef, { Info: this.currentInfo });
});
}).then(function() {
console.log("Transaction successfully committed!");
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
除了防止您当前拥有的无限循环外,这还可以防止多个用户在几乎同时更新文档时覆盖彼此的结果。
您可以使用 pipe 和 first 获取您需要的值,然后再次更新。
sendInfo(text: string) {
this.useruid = this.AngularAuth.auth.currentUser.uid;
this.db.collection('users').doc(this.useruid).valueChanges().pipe(first()).subscribe(a => {
const data = a.payload.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
}
this.db.collection('users').doc(this.useruid).update({
Info: this.currentInfo
})
}
rxjs的第一个方法用于获取一个observable发出的第一个值。之后,它取消订阅 observable。
我在使用 firebase 保存数据时遇到无限循环问题
this.db.collection('users').doc(this.useruid).update({Info: this.currentInfo})
private currentInfo:string[];
private useruid: string;
...
constructor(private AngularAuth: AngularFireAuth,
private db:AngularFirestore) { }
...
sendInfo(text:string){
this.useruid = this.AngularAuth.auth.currentUser.uid;
this.db.collection('users').doc(this.useruid).snapshotChanges().subscribe(a=>{
const data = a.payload.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
this.db.collection('users').doc(this.useruid).update({
Info: this.currentInfo
})...
})
}
举个例子,假设我目前有 currentInfo = ["a","b","c"]
和 text = "d"
,在 y 运行 方法 sendInfo( )
之后,
我得到一个循环:["a","b","c","d","a","b","c","d","d","a","b","c","d","a","b","c","d","d","d"...]
等等。
要根据文档的当前值更新文档,use a transaction:
var userDocRef = collection('users').doc(this.useruid);
return db.runTransaction(function(transaction) {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(userDocRef).then(function(userDoc) {
if (!userDoc.exists) {
throw "Document does not exist!";
}
const data = userDoc.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
transaction.update(userDocRef, { Info: this.currentInfo });
});
}).then(function() {
console.log("Transaction successfully committed!");
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
除了防止您当前拥有的无限循环外,这还可以防止多个用户在几乎同时更新文档时覆盖彼此的结果。
您可以使用 pipe 和 first 获取您需要的值,然后再次更新。
sendInfo(text: string) {
this.useruid = this.AngularAuth.auth.currentUser.uid;
this.db.collection('users').doc(this.useruid).valueChanges().pipe(first()).subscribe(a => {
const data = a.payload.data() as {name:string, Info:string[]};
data.Info.forEach(element => {
this.currentInfo.push(element);
});
this.currentInfo.push(text);
}
this.db.collection('users').doc(this.useruid).update({
Info: this.currentInfo
})
}
rxjs的第一个方法用于获取一个observable发出的第一个值。之后,它取消订阅 observable。