У меня довольно простая реализация периодического обновления некоторых объектов с немедленной повторной попыткой обновления при возникновении ошибки. Он опрашивает API через функцию анонимного вычисления, предоставленную конструктору объекта, в случае успеха он планирует следующее обновление после некоторого заданного Duration
, а при ошибке выдает состояние ошибки и пытается немедленно получить обновление.
class _StateUnderPolling {
final Duration _refreshPeriod;
final Computation _computation;
_StateUnderPolling(
this._refreshPeriod,
this._computation,
);
Observable<Monad<SuccessType>> poll() =>
Observable<Monad<SuccessType>>.fromFuture(_computation())
.flatMap(_emitSuccessAndScheduleUpdate)
.onErrorResume(_emitErrorAndPerformImmediateUpdate);
Stream<Monad<SuccessType>> _emitSuccessAndScheduleUpdate(SuccessType type) =>
_scheduleUpdate().startWith(Monad<SuccessType>._success(type));
Observable<Monad<SuccessType>> _scheduleUpdate() =>
Observable<Object>.timer(Object(), _refreshPeriod).flatMap((_) => poll());
Stream<Monad<SuccessType>> _emitErrorAndPerformImmediateUpdate(dynamic error) =>
poll().startWith(Monad<SuccessType>._error(error));
}
typedef Computation = Future<Monad<SuccessType>> Function();
Я полагаю, что новый метод poll()
должен на самом деле создать вызов метода "root", чтобы предыдущий Observable
впоследствии внутренне разыменовывался и собирал мусор, а вызов метода poll()
начинался в корне стека. .
Но проблема в том, что я получаю StackOverflowError
, который возникает, если computation
все время возвращает ошибку:
E / flutter (27986): [ERROR: flutter/lib/ui/ui_dart_state.cc(148)] Необработанное исключение: переполнение стека
E / flutter (27986): # 0 _ZoneDelegate.handleUncaughtError (dart: async / zone.dart: 699: 3)
E / флаттер (27986): # 1 runZoned. (dart: async / zone.dart: 1486: 16)
E / flutter (27986): # 2 _CustomZone.handleUncaughtError (dart: async / zone.dart: 1003: 19)
E / flutter (27986): # 3 _CustomZone.runUnaryGuarded (dart: async / zone.dart: 933: 7)
E / flutter (27986): # 4 _BufferingStreamSubscription._sendData (дарт: async / stream_impl. дротик: 336: 11)
E / флаттер (27986): # 5 _BufferingStreamSubscription._add (дарт: async / stream_impl.dart: 263: 7)
E / флаттер (27986):# 6 _StreamController._add (dart: async / stream_controller.dart: 764: 19)
E / flutter (27986): # 7 _rootRunUnary (dart: async / zone.dart: 1132: 38)
E / flutter (27986): # 8 _CustomZone.runUnary (dart: async / zone.dart: 1029: 19)
E / flutter (27986): # 9 _CustomZone.runUnaryGuarded (dart: async/zone.dart:931:7)
E / flutter (27986): # 10 _BufferingStreamSubscription._sendData (dart: async / stream_impl.dart: 336: 11)
E / flutter (27986): # 11 _BufferingStreamSubscription._add (dart: async / stream_impl.dart: 263: 7)
E / флаттер (27986): # 12 _StreamController._add (dart: async / stream_controller.dart: 764: 19)
E / флаттер (27986): # 13_rootRunUnary (dart: async / zone.dart: 1132: 38)
E / flutter (27986): # 14 _CustomZone.runUnary (dart: async / zone.dart: 1029: 19)
E / flutter (27986): # 15 _CustomZone.runUnaryGuarded (dart: async / zone.dart: 931: 7)
E / flutter (27986): # 16 _BufferingStreamSubscription._sendData (дарт: async / stream_impl.dart: 336: 11)
E / флаттер (27986): # 17 _BufferingStreamSubscription._add (дарт: async / stream_impl.dart: 263: 7)
E / флаттер (27986): # 18 _StreamController._add (dart: async / stream_controller.dart: 764: 19)
E / flutter (27986): # 19 _rootRunUnary (dart: async / zone.dart: 1132: 38)
Что я неправильно понимаю и как на самом деле "очистить" стек потока при новом вызове метода poll()
внутри flatMap
?