我的firebase实时数据库从一小部分按任意顺序排列的唯一元素开始。用户可以从这个列表中获取元素,从数据库中自动弹出它,这样其他用户就不能拥有相同的元素。用户还可以将弹出的元素返回到列表。这样,用户当前持有的元素和留在数据库中的元素就得到了保留。该列表足够小(最大27
元素),如果需要,我可以有效地将整个数据库内容加载到内存中。
我正在努力将这种行为表达到我的web (纯javascript) firebase应用程序中。我见过firebase transactions,但我不确定如何使用它们,以便弹出的子代被伪随机地选择。
这是一个违反原子性的不充分的尝试(用户可能最终弹出/获取相同的元素)
function popRandElem() {
// fetch all elements currently in db list
db.ref('list').get().then( (snap) => {
// choose random element
var elems = snap.val();
var keys = Object.keys(elems);
var choice = keys[ keys.length * Math.random() << 0 ];
// remove chosen element from db
db.ref('list').child(choice).remove();
return elems[choice];
}
}
myElem = popRandElem();
function restoreElem() {
db.ref('list').push(myElem);
myElem = null;
}
我如何修改这个例子,使popRandElem
从数据库中自动弹出?
发布于 2021-08-02 19:36:47
这对于事务来说很简单,使用可选的第二个回调来获得成功弹出的元素。
function popRandElemAsynch() {
var choice = null;
db.ref('list').transaction(
// repeats with updated list until run without collision
function( list ) {
// discard previous repetition choice
choice = null;
// edge-case of list emptied during transac repeats
if (!list)
return list;
// choose and remember a random element
var keys = Object.keys(list);
choice = keys[ keys.length * Math.random() << 0 ];
// remove the element
delete list[choice];
return list;
},
// runs once after above has run for final time
function() {
// choice is the final uniquely popped element
// if it is null, list was emptied before collision-free pop
someFunc(choice);
},
// don't trigger premature events from transaction retries
false
);
}
https://stackoverflow.com/questions/68629223
复制