Rozważmy następujący kodDart Błędy w wielopoziomowym kodu asynchronicznego
import 'dart:async';
Future main() async {
try {
print("trying");
await doSomething();
print("success");
} catch (e) {
print("caught");
}
}
Future<int> doSomething() async {
await doSomethingElse();
return 5;
}
Future<int> doSomethingElse() async {
throw new Exception();
}
Po uruchomieniu wyjątek rzucony w doSomethingElse()
się wciągnąć w main()
, i wszystko działa zgodnie z oczekiwaniami. Ale, powiedzmy, osoba, która napisała metodę doSomething()
, nie zdawała sobie sprawy, że doSomethingElse()
była asynchroniczna, i zamiast tego napisała następującą (zanotuj brakującą await
).
Future<int> doSomething() async {
doSomethingElse();
return 5;
}
Teraz wyjątek nie zostanie w ogóle złapany. Raczej wyjście teraz wygląda tak:
trying
success
Unhandled exception:
Uncaught Error: Exception
Stack Trace:
#0 doSomethingElse.<doSomethingElse_async_body> (file:///C:/code/test.dart:19:7)
#1 Future.Future.<anonymous closure> (dart:async/future.dart:118)
<snip>
Co się dzieje jest to, że doSomething()
wraca natychmiast, a potem jakiś czas później, w innym kontekście, doSomethingElse()
rzuca swój błąd, natychmiast zatrzymać wszystkie wykonanie. Wiem, że odpowiedź na to może brzmieć: "Cóż, nie rób tego wtedy." ale rozważam przypadki, w których mogę nie mieć kontroli nad metodami, do których dzwonię (powiedz, czy są częścią biblioteki).
Sytuacja ta prowadzi do kilku pokrewnych pytania:
- Jako autor
main()
, czy jest jakiś sposób mogę być pewny, że moje wezwanie dodoSomething()
nie zakończy się nieobsługiwany wyjątek? Czy jestem zależny od autoradoSomething()
, aby upewnić się, że wszystkie możliwe wyjątki są obsługiwane lub propagowane do zwróconej Przyszłości? Czy istnieje sposób na dołączenie jakiejś globalnej procedury obsługi błędów, która może wychwycić błędy z porzuconych kontraktów Futures? - Jako autor
doSomething()
, jeśli nie chcę czekać nadoSomethingElse()
(powiedzmy, że pisze na przykład w dzienniku, więc nie potrzebuję wyjścia ani nie muszę się martwić o błędy obsługi). Czy jest coś, co mogę zrobić, aby zapobiec błędom wdoSomethingElse()
od zatrzymania programu innego niż zawijanie każdego wywołania tego bloku try/catch (który może być uciążliwy i łatwo przeoczyć)? - Jako autor
doSomethingElse()
, istnieje jakiś wzór, którego mogę użyć, co pozwala mi rzutować wyjątki w taki sposób, że osoby oczekujące na zakończenie przyszłości mogą obsłużyć ten wyjątek, a osoby dzwoniące, które nie czekają na przyszłe wykłady. nie musisz się martwić o złapanie wyjątku? Moim zdaniem w tym względzie jest zwrócenie specjalnego obiektu zamiast wyrzucenia wyjątku, ale to dodaje wiele dodatkowych problemów i sprawia, że metoda jest znacznie trudniejsza.
Uwaga: Używam asynchroniczny/Oczekujcie składnia tutaj, ale kwestia ta powinna być równie istotne dla ściślej przyszłej budowy bazie (gdzie można powrócić nową przyszłość w doSomething()
zamiast .then()
ing wyłączyć jedną z doSomethingElse()
można obsługiwać te błędy z [stref] (https: // www. dartlang.org/articles/zones/) i są plany dodania procedury obsługi błędów najwyższego poziomu, ale nie sądzę, że jest to jeszcze zaimplementowane. –
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:isolate.Isolate#id_addErrorListener –
Funkcje lub metody klasy we właściwie zaimplementowanych bibliotekach jawnie byłyby synchroniczne lub asynchroniczne, a tylko te funkcje, które naprawdę potrzebują być tak asynchronicznym - tak jak teraz funkcje biblioteczne, zwracając przyszłość, jeśli są asynchroniczne. Nie używałem jeszcze tej składni, ale zakładam, że edytujący zgłosi błąd, gdy wykryją niedopasowania oczekujące/asynchroniczne. –