【问题标题】:Notification of final commit in batch transactions批处理事务中的最终提交通知
【发布时间】:2014-07-12 15:40:18
【问题描述】:

我有一个 Angular 应用程序,它允许用户“签出”选定的对象(他们会控制这些对象,直到放回对象池中),它的数量可以在 1 到多个之间。在 ref.transaction() 上使用 for 循环,我得到每个提交的对象的提交。根据这个问题Firebase dataRef.transaction() returns wrong snapshot 的答案,在服务器端,这些可能是批处理的,并且可能无法从批处理事务中获得准确的计数参考。如何判断所有提交的提交是否已完成(即批处理已完成)以及提交的最终计数?例如,我可以遍历 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 
            } 
        }
    );

【问题讨论】:

  • 如果没有显示您的问题的代码的最小示例,此问题将被关闭。
  • for(var y=0;y
  • 所以想法是在收到最后一次提交后,可以将进程传递给像 DOM 状态指示器这样的函数
  • 由于您清楚地使用了我对您上一个问题的回答 (stackoverflow.com/a/24704698/209103) 中的建议,如果您接受该答案会很好(通过单击它左侧的大复选标记) .见meta.stackexchange.com/questions/23138/…
  • 抱歉 - 但您的回复是评论而不是答案,我感谢您的评论。看起来复选标记只出现在答案中

标签: angularjs firebase angularfire


【解决方案1】:

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

按顺序触发事务

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

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”并简单地跟踪 check_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');
        }
    }
});

如果这导致您的客户端中的状态过多,您可以考虑将已签出的项目保存在不同的参考中。当用户签出一个项目时,您只需将其移动到这个CheckedOut ref。这样,您只需要监视该 ref 是否有任何孩子。

更新

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

更新 2

我可能在上次更新中错了。在this fiddle 中,child_changed 事件不会为已中止的transactions 触发(通过返回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)上测试了几个浏览器窗口,据我所知,我的客户端之间的状态保持一致。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多