首页 文章

返回的未来总是比预期值少1

提问于
浏览
2

我有以下飞镖码:

.dart

Future<int> currentMrn( ) async {
  var rootRef = await firebaseClient;
  var mrnRef = await rootRef.child( 'ids/mrn' );
  var event = await mrnRef.onValue.first;
  DataSnapshot ss = event.snapshot;

  return ss.val( );
}

Future<int> nextMrn( ) async {
  int curMrn = 0;
  var rootRef = await firebaseClient;
  Future<int> futureMrn = currentMrn( );

  futureMrn.then( ( int value ) {
    if ( value == null ) {
      rootRef.child('ids/mrn').set(curMrn);
      //futureMrn = Future.value([curMrn]);
    }
    else {
      curMrn = value + 1;
      rootRef.child('ids/mrn').set(curMrn);
      //futureMrn = Future.value([curMrn]);
    }
  } );

  return currentMrn( );
}

代码被称为:

.dart

nextMrn().then((int value) {
    print(value);
  });

但是,打印值总是比firebase中的值小1 .

似乎currentMrn()没有获得新的更新值 .

我在https://pub.dartlang.org/packages/firebase使用飞镖firebase包

谢谢你的帮助 .

编辑1

运行next.then(第一个版本)nextMrn()会引发以下异常

Exception: Uncaught Error: The null object does not have a method 'cancel'.

NoSuchMethodError: method not found: 'cancel'
Receiver: null
Arguments: []
Stack Trace:
#0      Object._noSuchMethod (dart:core-patch/object_patch.dart:42)
#1      Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
#2      _cancelAndValue (dart:async/stream_pipe.dart:58)
#3      Stream.first.<anonymous closure> (dart:async/stream.dart:937)
#4      _RootZone.runUnaryGuarded (dart:async/zone.dart:1104)
#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#6      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#7      _SyncBroadcastStreamController._sendData (dart:async/broadcast_stream_controller.dart:362)
#8      _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:237)
#9      Query._createStream.addEvent (package:firebase/src/firebase.dart:531:12)
#10     JsObject._callMethod (dart:js:678)
#11     JsObject.callMethod (dart:js:618)
#12     Query._createStream.startListen (package:firebase/src/firebase.dart:539:11)
#13     _runGuarded (dart:async/stream_controller.dart:769)
#14     _BroadcastStreamController._subscribe (dart:async/broadcast_stream_controller.dart:199)
#15     _ControllerStream._createSubscription (dart:async/stream_controller.dart:787)
#16     _StreamImpl.listen (dart:async/stream_impl.dart:474)
#17     Stream.first (dart:async/stream.dart:935)
#18     currentMrn.<currentMrn_async_body> (package:epimss_shared/src/epimss_shared_db_client.dart:34:36)
#19     _RootZone.runUnary (dart:async/zone.dart:1166)
#20     _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:494)
#21     _Future._propagateToListeners (dart:async/future_impl.dart:577)
#22     _Future._completeWithValue (dart:async/future_impl.dart:368)
#23     _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:422)
#24     _microtaskLoop (dart:async/schedule_microtask.dart:43)
#25     _microtaskLoopEntry (dart:async/schedule_microtask.dart:52)
#26     _ScheduleImmediateHelper._handleMutation (dart:html:42529)

上面第18行是指

var event = await mrnRef.onValue.first;

currentMrn()方法中的行 . 似乎试图取消一个事件 . 不确定 .

编辑2

因为所有先前的尝试都返回比预期更小的整数1,所以我将currentMrn()的代码直接包含在nextMrn()中,如下所示:

Future<int> currentMrn( ) async {
  var rootRef = await firebaseClient;
  var mrnRef = await rootRef.child( 'ids/mrn' );
  var event = await mrnRef.onValue.first;
  DataSnapshot ss = event.snapshot;

  return ss.val( );
}

Future<int> nextMrn( ) async {
  var curMrn = 0;

  var rootRef = await firebaseClient;
  var mrnRef = await rootRef.child( 'ids/mrn' );
  var event = await mrnRef.onValue.first;
  DataSnapshot ss = event.snapshot;

  var value = ss.val( );

  if ( value == null ) {
    curMrn += curMrn + 1;
    rootRef.child( 'ids/mrn' ).set( curMrn );
  }
  else {
    curMrn = value + 1;
    rootRef.child( 'ids/mrn' ).set( curMrn );
  }
  return curMrn;
  //TODO correct Bad state: Cannot fire new event. Controller is already firing an event
}

这在调用nextMrn()时正确返回预期值 . 但是,它会抛出以下异常:

FIREBASE WARNING: Exception was thrown by user callback.  
Uncaught Unhandled exception:
Bad state: Cannot fire new event. Controller is already firing an event
#0      _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:236)
#1      Query._createStream.addEvent (package:firebase/src/firebase.dart:531:12)
#2      JsObject._callMethod (dart:js:678)
#3      JsObject.callMethod (dart:js:618)
#4      Firebase.set (package:firebase/src/firebase.dart:258:9)
#5      nextMrn.<nextMrn_async_body> (package:epimss_shared/src/epimss_shared_db_client.dart:56:38)
#6      _RootZone.runUnary (dart:async/zone.dart:1166)
#7      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:494)
#8      _Future._propagateToListeners (dart:async/future_impl.dart:577)
#9      _Future._complete (dart:async/future_impl.dart:358)
#10     _cancelAndValue (dart:async/stream_pipe.dart:62)
#11     Stream.first.<anonymous closure> (dart:async/stream.dart:937)
#12     _RootZone.runUnaryGuarded (dart:async/zone.dart:1104)
#13     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341)
#14     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:270)
#15     _SyncBroadcastStreamController._sendData (dart:async/broadcast_stream_controller.dart:362)
#16     _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:237)
#17     Query._createStream.addEvent (package:firebase/src/firebase.dart:531:12)
  (anonymous function)

指向重构的nextMrn()中的以下行

rootRef.child( 'ids/mrn' ).set( curMrn );

两个问题:1 . 如何纠正 . 2.如何在nextMrn()中捕获错误?

谢谢

1 回答

  • 1
    Future<int> nextMrn( ) async {
      int curMrn = 0;
      var rootRef = await firebaseClient;
      Future<int> futureMrn = currentMrn( );
    
      // missing return leads to broken future chain
      return futureMrn.then( ( int value ) {
        if ( value == null ) {
          rootRef.child('ids/mrn').set(curMrn);
          //futureMrn = Future.value([curMrn]);
        }
        else {
          curMrn = value + 1;
          rootRef.child('ids/mrn').set(curMrn);
          //futureMrn = Future.value([curMrn]);
        }
      // add the actual return in the chain to ensure
      // id doesn't return before the calculation is completed
      }).then((_) => currentMrn( );
    }
    

    或者使用async / await

    Future<int> nextMrn( ) async {
      int curMrn = 0;
      var rootRef = await firebaseClient;
      var futureMrn = currentMrn( );
      var value = await futureMrn;
      if ( value == null ) {
        rootRef.child('ids/mrn').set(curMrn);
        //futureMrn = Future.value([curMrn]);
      }
      else {
        curMrn = value + 1;
        rootRef.child('ids/mrn').set(curMrn);
        //futureMrn = Future.value([curMrn]);
      }
      return currentMrn( );
    }
    

    我无法弄清楚你的代码究竟是什么意思 . 希望无论如何都有效 .

相关问题