Iva*_*hev 2 javascript firebase firebase-realtime-database
这是一个很好的做法,如果是的话,在不同情况下打破具有不同错误状态/消息的事务的正确方法是什么?
我有一个交易运行在一个“报价”条目上进行“座位”预订:
如果以下 3 个条件之一为真,我想中断它并将状态/消息返回给调用者函数。
如果一切正常,事务应该正常完成并将状态/消息返回到调用函数进行保留。
如果其中一个条件成立,我不确定如何中断交易。
这就是我的意思:
dealSeats = function(entryRef, data) {
const TAG = '[dealSeats]: ';
return entryRef.transaction((entry)=>{
if (entry) {
if ((entry.deals) && (entry.deals[data.uid])) {
**? how to break the transaction with state/message 'You already have a deal.' ? and how to handle it below ?**
} else if (entry.details.seatsCount >= data.details.seatsCount) {
entry.details.seatsCount -= data.details.seatsCount;
var deal = [];
deal.status = 'asked';
deal.details = data.details;
if (!entry.deals) {
entry.deals = {};
}
entry.deals[data.uid] = deal;
} else {
**? how to break the transaction with state/message 'Not enought seats.' ? and how to handle it below ?**
}
}
return entry;
**? how to check if 'entry' is really null ? i.e. offer does not exists ?** and break and handle it.
})
.then((success)=>{
return success.snapshot.val();
})
.catch((error)=>{
return Promise.reject(error);
});
}
Run Code Online (Sandbox Code Playgroud)
这是我在实时数据库中的数据:
activeOffers
-LKohyZ58cnzn0vCnt9p
details
direction: "city"
seatsCount: 2
timeToGo: 5
uid: "-ABSIFJ0vCnt9p8387a" ---- offering user
Run Code Online (Sandbox Code Playgroud)
这是邮递员发送的我的测试数据:
{
"data":
{
"uid": "-FGKKSDFGK12387sddd", ---- the requesting/asking user
"id": "-LKpCACQlL25XTWJ0OV_",
"details":
{
"direction": "city",
"seatsCount": 1,
"timeToGo": 5
}
}
}
Run Code Online (Sandbox Code Playgroud)
==== 更新了最终来源 ====
非常感谢 Renaud Tarnec!
所以这是我工作正常的最终来源。如果有人看到潜在的问题,请告诉我。谢谢。
dealSeats = function(entryRef, data) {
const TAG = '[dealSeats]: ';
var abortReason;
return entryRef.transaction((entry)=>{
if (entry) {
if ((entry.deals) && (entry.deals[data.uid])) {
abortReason = 'You already made a reservation';
return; // abort transaction
} else if (entry.details.seatsCount >= data.details.seatsCount) {
entry.details.seatsCount -= data.details.seatsCount;
var deal = [];
deal.status = 'asked';
deal.details = data.details;
if (!entry.deals) {
entry.deals = {};
}
entry.deals[data.uid] = deal;
// Reservation is made
} else {
abortReason = 'Not enought seats';
return; // abort transaction
}
}
return entry;
})
.then((result)=>{ // resolved
if (!result.committed) { // aborted
return abortReason;
} else {
let value = result.snapshot.val();
if (value) {
return value;
} else {
return 'Offer does not exists';
}
}
})
.catch((reason)=>{ // rejected
return Promise.reject(reason);
});
}
Run Code Online (Sandbox Code Playgroud)
唯一的痛苦是在 VSCode 终端中部署期间通过不返回任何值来警告有关此中止的警告:
warning Arrow function expected no return value consistent-return
Run Code Online (Sandbox Code Playgroud)
目前我不确定我是否可以做些什么。
在 Firebase API 参考文档中查看此文档:https ://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction
下面是来自这个文档的代码。看看如何return;用于中止事务(文档还说:“您通过不从更新函数返回值来中止事务”)。并注意onComplete()在事务完成时(在else if (!committed){} 内)调用的回调函数中如何处理这种特定情况。
// Try to create a user for ada, but only if the user id 'ada' isn't
// already taken
var adaRef = firebase.database().ref('users/ada');
adaRef.transaction(function(currentData) {
if (currentData === null) {
return { name: { first: 'Ada', last: 'Lovelace' } };
} else {
console.log('User ada already exists.');
return; // Abort the transaction.
}
}, function(error, committed, snapshot) {
if (error) {
console.log('Transaction failed abnormally!', error);
} else if (!committed) {
console.log('We aborted the transaction (because ada already exists).');
} else {
console.log('User ada added!');
}
console.log("Ada's data: ", snapshot.val());
});
Run Code Online (Sandbox Code Playgroud)
因此,恕我直言,您应该采用相同的模式,并在代码中询问“**?如何破坏交易”的地方采用相同的模式return;。
更新:您可以使用变量区分流产案例,如下所示。如果您通过 Firebase 控制台添加age值 > 20 到的节点users.ada.name,第一个流产原因将被“触发”。
var adaRef = firebase.database().ref('users/ada');
var transactionAbortionCause; //new variable
adaRef.transaction(function(currentData) {
if (currentData === null) {
return { name: { first: 'Ada', last: 'Lovelace' } };
} else if (currentData.name.age > 20) {
transactionAbortionCause = 'User ada is older than 20'; //update the variable
console.log('User ada is older than 20');
return; // Abort the transaction.
} else {
transactionAbortionCause = 'User ada already exists'; //update the variable
console.log('User ada already exists');
return; // Abort the transaction.
}
}, function(error, committed, snapshot) {
if (error) {
console.log('Transaction failed abnormally!', error);
} else if (!committed) {
console.log('We aborted the transaction because ' + transactionAbortionCause); //use the variable
} else {
console.log('User ada added!');
}
console.log("Ada's data: ", snapshot.val());
});
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,你也可以像在你的代码中那样使用 promise 来做到这一点。文档说交易返回一个非空的firebase.Promise包含{committed: boolean, snapshot: nullable firebase.database.DataSnapshot}并解释这个承诺“可以选择使用而不是onComplete回调来处理成功和失败”。
所以通过:
return;对你的流产两种情况,和committed布尔值您应该能够通过执行以下操作来处理代码中的流产情况
.then((result)=>{
if (result.commited) {... } else { /*abortion!*/}
})
Run Code Online (Sandbox Code Playgroud)
但是我还没有测试过这种方法
| 归档时间: |
|
| 查看次数: |
1949 次 |
| 最近记录: |