返回的 future 总是比预期值小 1
Returned future is always 1 less than the expected value
我有以下飞镖代码:
.飞镖
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( );
}
代码是这样调用的:
.飞镖
nextMrn().then((int value) {
print(value);
});
但是,打印的值总是比 firebase 中的值小 1。
似乎 currentMrn() 没有得到新的更新值。
我在 https://pub.dartlang.org/packages/firebase
使用 dart firebase 包
感谢您的帮助。
编辑 1
运行 nextMrn() 的 future.then(第一个版本)抛出以下异常
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
因为之前的所有尝试returns比预期的整数小 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
}
这正确 returns 调用 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() 中的错误?
谢谢
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( );
}
我无法真正理解您的代码的确切意图。希望它无论如何都有效。
我有以下飞镖代码:
.飞镖
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( );
}
代码是这样调用的:
.飞镖
nextMrn().then((int value) {
print(value);
});
但是,打印的值总是比 firebase 中的值小 1。
似乎 currentMrn() 没有得到新的更新值。
我在 https://pub.dartlang.org/packages/firebase
使用 dart firebase 包感谢您的帮助。
编辑 1
运行 nextMrn() 的 future.then(第一个版本)抛出以下异常
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
因为之前的所有尝试returns比预期的整数小 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
}
这正确 returns 调用 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() 中的错误?
谢谢
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( );
}
我无法真正理解您的代码的确切意图。希望它无论如何都有效。