Перехватить исключение, брошенное в прослушиватель

#dart #stream #listener #unhandled-exception

Вопрос:

Это мой первый пост на StackOverflow ! Я надеюсь, что это будет полезно для многих разработчиков ! Вот в чем проблема :

Я использую прослушиватель для проверки состояния устройства Bluetooth. В этом прослушивателе, если я получаю отключенное событие после подключенного события (пользователь отказался от сопряжения) => Я создаю исключение RefusedAssociationException();

 bool wasCo = false; 
bluetoothDevice.state.listen((event) async {
    
    if (event == BluetoothDeviceState.connected ||
          event == BluetoothDeviceState.connecting) wasCo = true;

    if (wasCo amp;amp; event == BluetoothDeviceState.disconnected) {
      print("We throw RefusedAssociationException");
      wasCo = false;
      throw RefusedAssociationException();
    }
}).onError((handleError) => print("HANDLE ERROR IS : $handleError"));

await bluetoothDevice.connect();
 

Этот код не позволяет мне обрабатывать исключение RefusedAssociationException().
Вот ошибка, которую я получаю :

 I/flutter (18595): We throw RefusedAssociationException
E/flutter (18595): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Instance of 'RefusedAssociationException'
E/flutter (18595): #0      BleLocalDataSourceImpl.connectToDevice.<anonymous closure> (package:tikee_remote_v2/features/tikee/data/datasources/local/ble_local_data_source.dart:107:9)
E/flutter (18595): #1      BleLocalDataSourceImpl.connectToDevice.<anonymous closure> (package:tikee_remote_v2/features/tikee/data/datasources/local/ble_local_data_source.dart:97:34)
E/flutter (18595): #2      _rootRunUnary (dart:async/zone.dart:1436:47)
E/flutter (18595): #3      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter (18595): #4      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
E/flutter (18595): #5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter (18595): #6      _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (18595): #7      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (18595): #8      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (18595): #9      _rootRun (dart:async/zone.dart:1420:47)
E/flutter (18595): #10     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (18595): #11     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (18595): #12     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (18595): #13     _rootRun (dart:async/zone.dart:1428:13)
E/flutter (18595): #14     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (18595): #15     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (18595): #16     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (18595): #17     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (18595): #18     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
 

Кто-нибудь знает, как перехватывать исключения, создаваемые слушателем ?
Какова здесь лучшая практика ?

Большое спасибо

Комментарии:

1. «Лучшая практика» действительно зависит от вашей идеологии, которая, как и бог, зависит от людей. Некоторые люди даже не верят… в обработку ошибок, то есть 😀 . Более серьезно, я бы использовал Either тип из любого функционального языка программирования для принудительной обработки ошибок. Вот статья об этом: medium.com/nerd-for-tech/…

2. Здравствуйте @Lulupointu, прежде всего спасибо за ваше время. Я рассматривал возможность использования любого типа (который, кстати, очень мощный), но в моем случае я не хочу прерывать поток и продолжать прослушивать после появления ошибки !

3. Извините, я не уверен в вашем комментарии. Вы ДЕЙСТВИТЕЛЬНО хотите продолжать слушать ?

Ответ №1:

Обратные stream.listen вызовы независимы. Если вы получаете событие данных, onData вызывается обратный вызов, если вы получаете ошибку из потока, onError вызывается событие. (Ваш onData обратный вызов также отмечен async без видимой причины, проверьте, необходимо ли это.)

Если вы выполняете любой из обратных вызовов, он становится неперехваченной асинхронной ошибкой и сообщается текущему Zone обработчику неперехваченных ошибок.

Ошибка в onData обратном вызове не передается onError обработчику, что, по-видимому, вы предполагаете.

Не совсем ясно, какого поведения вы хотите. Где должна всплыть ошибка, которую вы бросаете? Это должно положить конец listen ? (Если это так, запомните подписку и отмените ее, если только вы не знаете, что поток закроется сам по себе после этого события).

Комментарии:

1. Спасибо за ваш ответ, очень интересный контент.