【问题标题】:Firebase: Atomically pop random element from realtime databaseFirebase:从实时数据库中原子地弹出随机元素
【发布时间】:2023-03-11 17:56:02
【问题描述】:

我的 firebase 实时数据库以任意顺序的一小部分独特元素开始。用户可以从此列表中获取一个元素,从数据库中原子地弹出它,这样其他用户就不能拥有相同的元素。用户还可以将他们弹出的元素返回到列表中。这样,用户当前持有的元素以及留在数据库中的元素都得到了保存。该列表足够小(最多 27 个元素),如果需要,我可以有效地将整个数据库内容加载到内存中。

我正在努力将这种行为表达到我的网络(纯 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 原子地从数据库中弹出?

【问题讨论】:

    标签: javascript firebase firebase-realtime-database


    【解决方案1】:

    事实证明这对于事务来说很简单,使用可选的第二个回调来获取成功弹出的元素。

    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
        );
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-08
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-27
      相关资源
      最近更新 更多