在使用Firebase时,我通常使用AngularFire2。但是这次我没有,我使用了普通的Firebase库,因为当我检查AngularFire2上的文档以获取所需的交易用途时,我找不到了。
在使用正常的Firebase库时,我遇到了此错误,该错误表示未提交事务,但数据仍保存到Firebase。 有人可以指出我犯的错误吗?
这是我的代码:
saveSeats(key, numbers){
for (let i = 0; i < numbers.length; i++) {
const num = numbers[i].toString();
const objPath = `${this.basePath}/${key}/${num}`;
const busesRef = firebase.database().ref("buses/"+key+"/"+num);
busesRef.transaction(function(currentValue) {
if (currentValue === null) {
let newRow = JSON.stringify({ number: num, status: "reserved", timestamp: Date.now() });
busesRef.child("0").set(newRow);
} else {
console.log('Value Already Exists');
}
}, function(error, committed, snapshot) {
if (error) {
console.log('Transaction failed abnormally!', error);
}else if (!committed) {
console.log('We aborted the transaction (because number already exists).');
} else {
console.log('Number added!');
}
console.log("Number: ", snapshot.val());
});
}
}
答案 0 :(得分:1)
您不应在交易中使用doc所示的set()
方法:
注意:使用set()修改数据将取消所有未决的事务 在该位置,因此如果将set()和 transaction()更新相同的数据。
您应该“通过transaction()
一个更新函数,该函数用于将当前值转换为新值。”
因此,以下应正常工作:
busesRef.transaction(function(currentValue) {
if (currentValue === null) {
let newRow = JSON.stringify({ number: num, status: "reserved", timestamp: Date.now() });
return newRow; // <- Here the function returns the new value
} else {
console.log('Value Already Exists');
return; // Will abort the transaction.
}
},
....
最后,我认为您不需要对对象进行字符串化。请执行以下操作:
let newRow = { number: num, status: "reserved", timestamp: Date.now() };
return newRow;
或者,当然,简单地
return { number: num, status: "reserved", timestamp: Date.now() };
进一步的考虑:
我注意到您将事务封装在for
循环中,这意味着您将修改不同busesRef
节点的值。您不应该在一次交易中进行所有这些修改吗?而不是通过一组“原子”事务,每个事务都会修改给定busesRef
节点的值?这取决于您的确切用例。