Angular 在 firebase 中使用事务的正确方法是什么
What is the proper way to use transactions in firebase with Angular
我通常在使用 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());
});
}
}
您不应在交易中使用 set()
方法,如 doc:
中所示
Note: Modifying data with set() will cancel any pending transactions
at that location, so extreme care should be taken if mixing set() and
transaction() to update the same data.
你应该"pass transaction()
an update function which is used to transform the current value into a new value."
所以下面应该正常工作:
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
节点的值。您不应该在一次交易中进行所有这些修改吗?而不是一组 "atomic" 交易,每个交易都会修改给定 busesRef
节点的值?这取决于您的确切用例。
我通常在使用 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());
});
}
}
您不应在交易中使用 set()
方法,如 doc:
Note: Modifying data with set() will cancel any pending transactions at that location, so extreme care should be taken if mixing set() and transaction() to update the same data.
你应该"pass transaction()
an update function which is used to transform the current value into a new value."
所以下面应该正常工作:
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
节点的值。您不应该在一次交易中进行所有这些修改吗?而不是一组 "atomic" 交易,每个交易都会修改给定 busesRef
节点的值?这取决于您的确切用例。