Firebase允许以事务方式更新资源.据我了解,客户端这样做就是向服务器发送请求"如果旧值是X,则使新值为Y".如果存在争用,则服务器可以拒绝来自客户端的多个更新,直到接受一个更新.
现在,如果我想原子地更新多个资源怎么办?
如果接受第一个更新会发生什么,然后在接受第二个更新之前断开客户端连接.有没有办法在原子事务中包含多个更新?如果没有,是否有这个问题的惯用解决方案?
And*_*Lee 44
UPDATE
现在可以原子地更新多个位置.有关详细信息,请参阅此博文.
var mergedUpdate = {};
mergedUpdate[ 'users/' + userId + '/widgets/' + widgetId ] = true;
mergedUpdate[ 'widgets/' + widgetId ] = widgetData;
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.update(mergedUpdate);
Run Code Online (Sandbox Code Playgroud)
这不会强制执行事务数据(如果值当前为X,则使其为Y),但此部分可以移至安全规则.例如,如果我们想要同时更新两个计数器,我们可以添加如下规则:
{
"counter1": {
".validate": "newData.val() === (data.val()||0)+1"
},
"counter2"1 {
".validate": "newData.val() === (data.val()||0)+1"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以尝试与上面相同的多路径更新.如果自上次从服务器读取值以来值已更改,则尝试将失败.我们可以检查if( error.code === 'PERMISSION_DENIED' ) { ... }失败是否是由验证引起的,并相应地重试.
原始邮政
执行此操作的唯一方法是在共同祖先上运行事务.
例如,如果要更新/ a/b/c和/ a/x/y,可以在/ a运行事务并更改这两个值.
这种方法的缺点是网络I/O可能很昂贵,因为事务中的所有数据都需要下载然后发送回服务器.
您可能需要考虑的更复杂但可能更强大的方法是重构数据,以便存储编辑历史记录而不是存储实际值.例如,如果您要存储银行余额信息,则可以存储存款和取款历史记录.然后,当您想要获得平衡时,您将回放整个历史记录并计算最终余额.
这种方法的优点是它可以让你进行原子更新.例如,如果您将资金从accountA转移到accountB,您只需在日志末尾附加一个元素,即"从帐户A转帐到帐户B N美元".附加单个元素是原子操作.
这是我们使用Firepad(我们的协作文本编辑器)采用的方法.
| 归档时间: |
|
| 查看次数: |
11559 次 |
| 最近记录: |