Firebase如何检查交易成功或失败? [英] Firebase how to check transaction success or fail?

查看:179
本文介绍了Firebase如何检查交易成功或失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在事务中更新一个firebase节点,简单的东西。跟随文档:

https://www.firebase.com/docs/ios/guide/saving-data.html

  Firebase * upvotesRef = [[Firebase alloc] initWithUrl:@https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes]; 
$ b $ [upvotesRef runTransactionBlock:^ FTransactionResult *(FMutableData * currentData){
NSNumber * value = currentData.value;
if(currentData.value == [NSNull null]){
value = 0;

[currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]]];
return [FTransactionResult successWithValue:currentData];
}];

最大的问题是:
如何检查此次交易的结果(成功/失败)?我希望做一些UI更改取决于它的结果。

有另一种方法在SDK文件中显示有回调,但它没有解释我应该检查哪个值。而且它说有关该方法的东西可以运行多次。如何确定何时给出最终结果?
https:/ /www.firebase.com/docs/ios-api/Classes/Firebase.html#//api/name/runTransactionBlock:andCompletionBlock



对不起这样的初学者,苹果风格的文档真的没有一些例子聚集在一起。

/ em>要等待最后的值, runTransactionBlock:andCompletionBlock:是您想要查看的方法。以下是一些示例代码:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' currentData.value;
if(currentData.value == [NSNull null]){
value = 0;

[currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]]];
return [FTransactionResult successWithValue:currentData];
} andCompletionBlock:^(NSError * error,BOOL committed,FDataSnapshot * snapshot){
if(error){
NSLog(@Error:%@,error);

if(committed){
NSLog(@Data committed);
}
NSLog(@Final Value:%@,snapshot.value);
}];

最后一个值, snapshot.value 在哪里你可以得到你的最终价值。如果您使用 observeEventType:withBlock:


,那么它与您获得的 FDataSnapshot

如果出现问题,您将得到错误

如果你的数据被提交, commit 将会是YES。如果您在交易块中返回 [FTransactionResult abort] 而不是 [FTransactionResult successWithValue:] 提交将是NO。



这意味着,如果您在4读取计数器并尝试更新它。您可能会尝试在别人同时更新计数器。如果你先进入, snapshot.value 将会是5.如果另一个人的更新进入之前, snapshot.value 将会是6.



无论谁先投了票,你可能都要达到6。要做到这一点,你需要添加一个观察者。代码如下:
$ b $ pre $ [upvotesRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot * snapshot){
NSLog(@New Value:%@,snapshot.value);
}];

有了这个,你不需要 完成块来找出最后的价值是因为每次事务阻塞,观察者块都会被触发。在上面的示例场景中,无论先进先出是谁,都会一次启动5次,每次启动6次。如果你想知道你的特定交易是否成功,那么你确实需要完成区块,而不是现在这个位置的价值。

完成,还有一个方法叫做 runTransactionBlock:andCompletionBlock:withLocalEvents:。如果其他人也正在写入相同的位置,事务块可能会运行多次。如果发现它在陈旧的数据上运行,就会发生这种情况。当它在新数据上成功运行时,它将调用完成块。然而,你会发现每次运行时,都会触发该位置的任何观察者块。如果你不希望发生这种情况,你应该把NO传给 withLocalEvents:。您的Firebase会在确认的写入完成时在该位置触发事件,但未经确认的本地事务临时写入将不会被触发。

回顾一下这个例子,你和另一个人正试图同时upvote。默认情况下,当您尝试将计数从4更新为5时,观察者将立即触发。实际的事务可能会失败,因为其他人同时将上移计数从4推到了5。然后您的事务块将会以新数据5再次运行,并看到它应该将计数值推到6.当本地事件设置为NO时,观察者将在服务器让您知道其他人将推动计数从4到5,而不是当你试图更新计数从4到5.



这不是一个像upvotes简单的东西,每个人都只是递增,但是如果你可能会推送来自其他用户的不同数据,那么在这个位置的任何观察者可能会看到数据在最终解决之前跳来跳去。


I am trying to update a firebase node in transaction, simple stuff. Followed the doc:

https://www.firebase.com/docs/ios/guide/saving-data.html

Firebase* upvotesRef = [[Firebase alloc] initWithUrl: @"https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes"];

[upvotesRef runTransactionBlock:^FTransactionResult *(FMutableData *currentData) {
    NSNumber *value = currentData.value;
    if (currentData.value == [NSNull null]) {
      value = 0;
    }
    [currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]];
    return [FTransactionResult successWithValue:currentData];
}];

The big question is: How do I check the outcome of this transaction(success/fail)? I wish to make some UI changes depends on the outcome of it.

There is another method in SDK document appears to have a callback, but it did not explain which value should I check against. And it says something about the method could be run multiple times. How do I make sure when it gives the "final" result? https://www.firebase.com/docs/ios-api/Classes/Firebase.html#//api/name/runTransactionBlock:andCompletionBlock:

Sorry I am such a beginner that apple style doc really doesn't come together without some examples.

解决方案

If you just want to wait for the final value, runTransactionBlock:andCompletionBlock: is the method you want to look at. Here's some example code:

[upvotesRef runTransactionBlock:^FTransactionResult *(FMutableData *currentData) {
    NSNumber *value = currentData.value;
    if (currentData.value == [NSNull null]) {
        value = 0;
    }
    [currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]];
    return [FTransactionResult successWithValue:currentData];
} andCompletionBlock:^(NSError *error, BOOL committed, FDataSnapshot *snapshot) {
    if (error) {
        NSLog(@"Error: %@", error);
    }
    if (committed) {
        NSLog(@"Data committed");
    }
    NSLog(@"Final Value: %@", snapshot.value);
}];

That last value there, snapshot.value is where you can get your final value. It's the same sort of FDataSnapshot that you get if you use observeEventType:withBlock:

If something goes wrong, you'll get an error.

If your data is committed, committed will be YES. If you returned [FTransactionResult abort] in your transaction block instead of [FTransactionResult successWithValue:], committed will be NO.

This means, if you read the counter at 4 and try to update it. You might try to update the counter at the same time someone else does. If yours get in first, snapshot.value will be 5. If the other person's update gets in before you do, the snapshot.value will be 6.

You probably wanted to get up to 6 no matter who upvoted first. To do this, you need to add an observer. The code for that might look like:

[upvotesRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
    NSLog(@"New Value: %@", snapshot.value);
}];

With this, you don't need the completion block to find out the final value because every time the transaction blocks, the observer block will fire. In the example scenario above, it would fire once for 5 and once for 6 no matter who upvoted first. You do need the completion block if you want to find out whether or not your particular transaction succeeded and not just what value is at that location now.

And, just to be complete, there is one more method called runTransactionBlock:andCompletionBlock:withLocalEvents:. If others are also writing to the same location, the transaction block may run multiple times. This happens if it finds out that it is running on stale data. When it runs successfully on fresh data, it will call the completion block. However, you'll find that each time it runs, it will fire any observer blocks at that location. If you don't want this to happen, you should pass NO to withLocalEvents:. Your Firebase will trigger events at that location whenever a confirmed write goes through, but your local transaction's temporary writes, which are unconfirmed, will not.

Looking back to the example where you and another person are trying to upvote at the same time. By default, the observer will fire as soon as you try to update the count from 4 to 5. The actual transaction might fail because someone else pushed the upvote count from 4 to 5 at the same time. Your transaction block would then run again with the new data, 5, and see that it should push the count to 6. With local events set to NO, the observer will fire after the server lets you know someone else pushed the upvote count from 4 to 5, and not when you try to update the count from 4 to 5.

This isn't a huge deal with something simple like upvotes where everyone is just incrementing, but if you could potentially be pushing different data from other users, any observers at the location may see the data jump around before finally settling.

这篇关于Firebase如何检查交易成功或失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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