NodeJS中的Firebase事务总是运行3次? [英] Firebase transactions in NodeJS always running 3 times?

查看:138
本文介绍了NodeJS中的Firebase事务总是运行3次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每当我在NodeJS中定义一个Firebase事务时,我发现它总是运行三次 - 前两次使用null数据,最后第三次使用实际的数据。这是正常的/意图吗?



例如这个代码:

  firebaseOOO.child('ref')。transaction(function(data){
console.log(data);
return data;
});

输出以下内容:

  null 
null
i1:{a1:true}





要回答评论中的问题,这里和回调一样:


$ b $ pre $ firebaseOOO.child('ref')。transaction(function(data){
console.log(data); $ b $ (b)返回数据;
},函数(错误,提交,快照){
if(error)
console.log('failed');
else if(!committed)
console.log('aborted');
else
console.log('committed');
console.log('fin');
}) ;

产生以下输出:

  null 
null
i1:{a1:true}
承诺
fin

我已经在发布问题之前阅读了事务处理的细节,所以我曾尝试将applyLocally设置为false,如下所示:

  firebaseOOO.child('ref')。transaction(function(data){
console.log('hit');
return data;
},function(){},false);

但是它仍然击中3次(只是双重检查),所以我认为它是不同的。在交易之前获得价值是否如预期的那样有效,因为它只会触及一次,而且不管局限性是什么,所以我不确定什么是适用的。这就是我的意思是通过在交易之前取得价值:

pre $ firebaseOOO.child('ref')。once('value' ,函数(data){
console.log('1');
firebaseOOO.child('ref')。transaction(function(data){
console.log('2' );
返回数据;
});
});

输出:

  1 
2

@Michael:怎样才能使用这个行为?事务主要是为了让数据本身用来修改自己 - 原型增量++的情况。所以如果我需要给现有值10增加1,并继续使用11的结果,前两次函数命中我会得到一个我需要处理的错误结果,最后是正确的结果第三次打11。我怎样才能使用这两个最初的1?另一个场景(也许我不应该使用这个事务,但如果它像我期望的那样工作,它使更干净的代码)是插入一个值,如果它还不存在。如果事务只触发一次,则空值将意味着该值不存在,因此您可以在此情况下将计数器初始化为1,否则将值加1。嘈杂的空值,这是不可能的。



这似乎是从这一切是简单地使用一次模式经常比不?

一次交易模式:

  firebaseOOO.child('ref')。once 'value',函数(data){
console.log('1');
firebaseOOO.child('ref')。transaction(function(data){
console.log '2');
返回数据;
});
});


解决方案

您在这里看到的行为与Firebase会触发本地事件,然后最终与Firebase服务器同步。在这个具体的例子中,运行三次只会在第一次运行代码时发生 - 在这之后,状态已经完全同步,并且从那时起只会触发一次。此行为在此处详述: https://www.firebase.com/docs/transactions.html

Whenever I define a Firebase transaction in NodeJS I notice it always runs three times - the first two times with null data, then finally a third time with actually data. Is this normal/intended?

For example this code:

firebaseOOO.child('ref').transaction(function(data) {
    console.log(data);
    return data;
});

outputs the following:

null
null
i1: { a1: true }

I would have expected that it only print the last item.

To answer a question in the comments, here is the same with a callback:

firebaseOOO.child('ref').transaction(function(data) {
    console.log(data);
    return data;
}, function(error, committed, snapshot) {
    if (error) 
        console.log('failed');
    else if (!committed)
        console.log('aborted');
    else 
        console.log('committed');
    console.log('fin');
});

Which yields the following output:

null
null
i1: { a1: true }
committed
fin

I had read the details of how transactions work before posting the question, so I had tried setting applyLocally to false like this:

firebaseOOO.child('ref').transaction(function(data) {
    console.log('hit'); 
    return data; 
}, function(){}, false);

But it still hits 3 times (just double-checked) so I thought it was something different. Getting the 'value' before transacting does "work" as expected, in that it only hits once, and that's regardless of what applyLocally is set to, so I'm not sure what applyLocally does? This is what I mean by getting the value before transacting:

firebaseOOO.child('ref').once('value', function(data) {
    console.log('1');
    firebaseOOO.child('ref').transaction(function(data) {
        console.log('2');
        return data;
    });
});

Outputs:

1
2

@Michael: How can one make use of this behavior? Transactions are primarily for having data use itself to modify itself - the prototypical increment++ scenario. So if I need to add 1 to the existing value of 10, and continue working with the result of 11, the first two times the function hits I will have an erroneous result of 1 that I need to handle, and finally the correct result of 11 on the third hit. How can I make use of those two initial 1's? Another scenario (and maybe I shouldn't be using transactions for this, but if it worked like I expected it makes for cleaner code) is to insert a value if it does not yet exist. If transactions only hit once, a null value would mean the value does not exist, and so you could, for example, init the counter to 1 in that case, otherwise add 1 to whatever the value is. With the noisy nulls, this is not possible.

It seems the takeaway from all this is to simply use the 'once' pattern more often than not?

ONCE TRANSACTION PATTERN:

firebaseOOO.child('ref').once('value', function(data) {
    console.log('1');
    firebaseOOO.child('ref').transaction(function(data) {
        console.log('2');
        return data;
    });
});

解决方案

The behavior you're seeing here is related to how Firebase fires local events and then eventually synchronizes with the Firebase servers. In this specific example, the "running three times" will only happen the very first time you run the code—after that, the state has been completely synchronized and it'll just trigger once from then on out. This behavior is detailed here: https://www.firebase.com/docs/transactions.html (See the "When a Transaction is run, the following occurs" section.)

If, for example, you have an outstanding on() at the same location and then, at some later time, run this same transaction code, you'll see that it'll just run once. This is because everything is in sync prior to the transaction running (in the ideal case; barring any normal conflicts, etc).

这篇关于NodeJS中的Firebase事务总是运行3次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆