批处理事务中最后提交的通知



我有一个Angular应用程序,它允许用户"签出"选定的对象(他们将控制这些对象,直到把它们放回对象池中),这些对象的编号可以在1到许多之间。使用ref.transaction()上的for循环,我得到每个提交对象的提交。根据这个问题的答案,Firebase dataRef.transaction()返回错误的快照,在服务器端,这些快照可能是批处理的,并且可能无法从批处理的事务中获得准确的计数引用。如何判断所有提交的提交是否已经完成(即批处理已经完成)以及提交的最终计数?例如,我可以循环遍历50个"签出"请求,但可能只返回不到50个提交,因为另一个用户在事务完成之前签出了一个对象。我没有成功地使用事务回调来做到这一点。

for(var y=0;y<$scope.stuffSelected.length;y++) {
    var myObjectsRef = new Firebase(thisFBRef);
    myObjectsRef.transaction(
        function(anobject) {
            var update = {checkedout:true, checkout_by:'Sammy B', checkout_date: new Date().toUTCString()}; 
            for(var prop in update){ 
                anobject[prop] = update[prop]; 
            } 
            return anobject; 
        }, function(error, committed, snapshot) { 
            if(committed && !error){ 
                console.log('Commit successful ...'); // need someway to identify when this loop is finished 
            } 
        }
    );

您的问题来自于您试图将多个并行异步调用滚动到一个循环中的事实。

按顺序触发事务

可以通过顺序触发事务来解决这个问题。因此,您将只在当前事务的完成回调之后为下一个项目启动事务。

function checkout() {
    if (stuffToCheckout.length > 0) {
        myObjectsRef.child(stuffToCheckout[0]).transaction(function(anobject) {
            var update = {checkedout:true, checkout_by:'Sammy B', checkout_date: new Date().toUTCString()}; 
            for(var prop in update){ 
                anobject[prop] = update[prop]; 
            } 
            return anobject; 
        }, function(error, committed, snapshot) { 
            if(committed && !error){ 
                console.log('Commit successful ...');
                stuffToCheckout.shift();
                checkout();
            }
        }
    }
}
checkout([/* populate this list with the ids of items to check out*/]);

监听更新后的值

或者,您可以查看派生是否仍然从数据结构中检出任何内容。您可以监听项目上的'child_changed',并简单地跟踪checked_out标志:

var checkedOut = {};
items.on('child_changed', function(snapshot) {
    var val = snapshot.val();
    if (val.checked_out) {
        checkedOut[snapshot.name()] = true;
    }
    else {
        delete checkedOut[snapshot.name()];
        if (checkedOut.length == 0) {
            alert('Nothing is checked out anymore');
        }
    }
});

如果这导致你的客户端有太多的状态,你可以考虑把签出的项目放在不同的ref中。当用户签出一个项目时,你只需要把它移到这个CheckedOut ref中。这样你只需要监视这个ref是否有任何子ref。

更新

我刚刚意识到侦听更新的值将不起作用,因为child_changed事件将在本地触发(因此您将在服务器上提交之前看到本地更改)。按顺序处理事务似乎仍然是一个可行的选择。

更新2

我可能在上次更新中出错了。在这种情况下,child_changed事件不会为已经终止的transaction事件触发(通过返回undefined)。

代码中最相关的位是:

items.child(i).transaction(function(current_value) {
    if (!current_value.checked_out_by) {
        // not checked out -> check it out
        current_value.checked_out_by = username;
    }
    else if (current_value.checked_out_by == username) {
        // checked out by me -> check it in
        delete current_value.checked_out_by;
    }
    else {
        // checked out by someone else -> abort transaction
        return;
    }
    return current_value;
}, function(error, committed, snapshot) {
    if (error) {
        console.log('error callback: '+error);
        throw error;
    } else if (!committed) {
        console.log('not committed callback');
        console.log(snapshot.val()); // this is unmodified, so no need to update
    } else {
        console.log('success callback: '+snapshot.val().name);
    }
});

在我调用console.log(snapshot.val())的地方,它显示了未修改的值,这是我在之前的最后一个child_changed事件中获得的相同值。我在一台机器上测试了几个浏览器窗口(IE, Firefox, Chrome),据我所见,我的客户端状态保持一致。

相关内容

  • 没有找到相关文章

最新更新