StackOverflow в RxDart, даже если цепочка продолжается с новой наблюдаемой - PullRequest
0 голосов
/ 11 декабря 2019

У меня довольно простая реализация периодического обновления некоторых объектов с немедленной повторной попыткой обновления при возникновении ошибки. Он опрашивает 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?

...