Obsługa błędów
Uwaga
Opisane w tym artykule zachowanie jest dostępne tylko wtedy, gdy funkcja w wersji zapoznawczej Zarządzanie błędami na poziomie formuły w obszarze Ustawienia>Nadchodzące funkcje>Wersja zapoznawcza jest włączona. Więcej informacji: Kontrolowanie włączonych funkcji
Błędy się zdarzają. Sieci nie działają, magazyn wypełnia się, pojawiają się nieoczekiwane wartości. Ważne jest, aby logika nadal działała prawidłowo w przypadku ewentualnych problemów.
Domyślnie błędy przepływają przez formuły aplikacji i są zgłaszane do użytkownika końcowego aplikacji. Dlatego użytkownik końcowy wie, że stało się coś nieoczekiwanego, i może rozwiązać problem przy użyciu innych danych wejściowych lub zgłosić problem właścicielowi aplikacji.
Jako twórca aplikacji możesz kontrolować błędy w swojej aplikacji:
- Wykrywanie i obsługa błędu. Jeśli istnieje prawdopodobieństwo wystąpienia błędu, można utworzyć formuły aplikacji, aby wykrywać warunek błędu i ponawiać operację. Użytkownik końcowy nie musi się martwić, że wystąpił błąd, ponieważ twórca uwzględnił tę możliwość. Odbywa się to za pomocą funkcji IfError, IsError i IsErrorOrBlank w formule.
- Raportowanie błędu. Jeśli błąd nie jest obsługiwany w formule, w której wystąpił, jest on przekazywany do procedury obsługi App.OnError. Tutaj nie można zastąpić błędu, ponieważ już wystąpił i jest elementem obliczeń formuł. Można jednak użyć procedury App.OnError do kontrolowania sposobu raportowania błędu użytkownikowi końcowego, w tym całkowitego pomijania raportowania błędu. App.OnError zapewnia również typowy punkt przewężenia do raportowania błędów w całej aplikacji.
- Tworzenie i ponowne ustawianie błędu. Na koniec możesz wykryć warunek błędu przy użyciu własnej logiki, czyli warunku specyficznego dla Twojej aplikacji. Użyj funkcji Error do utworzenia błędów niestandardowych. Funkcja Error jest również używana do ponownego ustawiania błędu po sprawdzeniu go w funkcji IfError lub App.OnError.
Rozpoczynanie pracy
Zacznijmy od prostego przykładu.
- Utwórz nowy ekran w aplikacji kanwy Power Apps.
- Wstaw kontrolkę TextInput. Zostanie ona domyślnie nazwana TextInput1.
- Wstaw kontrolkę Label.
- Ustaw właściwość Text kontrolki Label na formułę
1/Value( TextInput1.Text )
Wystąpił błąd, ponieważ domyślnym tekstem kontrolki TextInput jest "Text input"
, którego nie można przekonwertować na liczbę. Domyślnie jest to dobrym rozwiązaniem: użytkownik końcowy otrzyma powiadomienie, że coś nie działa zgodnie z oczekiwaniami w aplikacji.
Nie chcemy, aby przy każdym uruchomieniu tej aplikacji wystąpił błąd. Najprawdopodobniej "Text input"
nie jest właściwą wartością domyślną dla pola wejściowego tekstu. Aby to naprawić, zmieńmy właściwość domyślną Default kontrolki TextInput na:
Blank()
Teraz mamy inny błąd. Operacje matematyczne z wartością pustą, takie jak dzielenie, będą wymuszać ustawienie wartości pustej na zero. To powoduje teraz błąd dzielenia przez zero. Aby rozwiązać ten problem, należy zdecydować, jakie zachowanie będzie odpowiednie w tej aplikacji. Odpowiedzią może być wyświetlanie wartości pustej, gdy tekstowe dane wejściowe są puste. Ten cel można osiągną, owijając formułę przy użyciu funkcji IfError:
IfError( 1/Value( TextInput1.Text ), Blank() )
Teraz błąd jest zastępowany prawidłową wartością, a banner błędu zniknął. Można jednak wybrać złe rozwiązanie: użyta funkcja IfError dotyczy wszystkich błędów, w tym wpisanie nieprawidłowej wartości, np. "hello"
. Można to rozwiązać, dostrajając funkcję IfError w celu obsługi tylko przypadku dzielenia przez zero i ponownego zgłaszania wszystkich innych błędów.
IfError( 1/Value( TextInput1.Text ),
If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )
Uruchommy więc aplikację i wypróbujmy kilka różnych wartości.
Bez żadnej wartości, tak jak podczas uruchamiania aplikacji, żadna odpowiedź nie jest wyświetlana, ponieważ wartość domyślna jest pusta, ale nie jest również wyświetlany błąd, ponieważ funkcja IfError zastępuje błąd dzielenia przez zero.
Po wpisaniu 4 jest oczekiwany wynik 0,25:
Jeśli wpiszemy coś niedozwolonego, np. hello
, zobaczymy baner błędu:
Jest to prosty przykład wstępny. Obsługa błędów może być wykonywana na wiele różnych sposobów, w zależności od potrzeb aplikacji:
- Zamiast baneru błędu możemy wyświetlać ciąg "#Error" w kontrolce etykiety z formułą. Aby zachować zgodność typów zamienników z pierwszym argumentem dla funkcji IfError, musimy jawnie przekonwertować wynik numeryczny na ciąg tekstowy przy użyciu funkcji Text.
IfError( Text( 1/Value( TextInput1.Text ) ), If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
- Zamiast owijać to konkretne wystąpienie przy użyciu funkcji IfError, można napisać scentralizowaną procedurę obsługi App.OnError. Nie można zastąpić ciągu wyświetlanego przy użyciu ciągu "#Error", ponieważ błąd już wystąpił, a procedura App.OnError jest udostępniana tylko w przypadku raportowania dla kontrolek.
If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
Propagowanie błędów
Błędy przepływają przez formuły tak samo jak w programie Excel. Na przykład w programie Excel, jeśli komórka A1
zawiera formułę =1/0
, w komórce A1 pojawi się wartość błędu #DIV0!
:
Jeśli komórka A2
odwołuje się do A1
przy użyciu formuły, takiej jak =A1*2
, błąd jest także propagowany za pośrednictwem tej formuły:
Błąd zastępuje wartość, która w przeciwnym razie zostałaby obliczona. Nie ma wyniku mnożenia w komórce A2
, tylko błąd dzielenia w komórce A1
.
Program Power Fx działa w ten sam sposób. Ogólnie rzecz biorąc, jeśli błąd jest podany jako argument dla funkcji lub operatora, operacja nie zostanie wykonana, a w wyniku operacji nastąpi przepływ błędu wejściowego. Na przykład Mid( Text( 1/0 ), 1, 1 )
zwróci błąd dzielenia przez zero, ponieważ najbardziej wewnętrzny błąd przechodzi przez funkcję Text i funkcję Mid:
Generalnie błędy nie przepływają przez właściwości kontrolki Power Apps. Rozszerzmy poprzedni przykład o dodatkową kontrolkę wyświetlaną, gdy właściwość Text
jest w stanie błędu:
Błędy nie są propagowane za pomocą kontrolki, ponieważ system będzie obserwował błędy wejściowe dla wszystkich właściwości kontrolki. Błąd nie zostanie utracony.
Większość funkcji i operatorów działa zgodnie z regułą „błąd wchodzi, błąd wychodzi”, ale istnieją pewne wyjątki. Funkcje IsError, IsErrorOrBlank i IfError są przeznaczone do pracy z błędami, więc mogą nie zwracać błędów, nawet jeśli zostanie do nich przekazany jeden z nich.
Obserwowanie błędów
Błędy nie są obserwowane, dopóki nie zostanie użyta ich wartość.
W wyniku funkcje If i Select mogą również nie zwracać błędu, jeśli zostanie do nich przekazany jeden z nich. Weź pod uwagę formułę If( false, 1/0, 3 )
. W tej formule istnieje błąd dzielenia przez zero, ale ponieważ funkcja If
nie uwzględnia tego odgałęzienia z powodu wartości false
, programy Power Fx i Power Apps nie zgłoszą błędu:
Użycie funkcji Set z błędem nie spowoduje zgłoszenia błędu w momencie, gdy błąd zostanie umieszczony w zmiennej. Na przykład w usłudze Power Apps istnieje formuła w procedurze App.OnStart, która umieszcza błąd dzielenia przez zero w zmiennej x
:
Nie jest zgłaszany błąd, ponieważ nie ma odwołania do x
. Jednak w momencie dodania kontrolki etykiety i ustawienia właściwości Text na x
zostanie wyświetlony błąd:
Błędy w formule można zaobserwować przy użyciu funkcji IfError, IsError i IsErrorOrBlank. Funkcjami tymi można zwrócić alternatywną wartość, podjąć alternatywną akcję lub zmodyfikować błąd przed jego zaobserwowaniem i zgłoszeniem.
Raportowanie błędów
Po zaobserwowaniu błędu kolejnym krokiem jest zgłoszenie błędu do użytkownika końcowego.
W przeciwieństwie do programu Excel nie zawsze jest wygodne miejsce do pokazywania wyniku błędu, ponieważ wynik formuły może spowodować, że właściwość, taka jak X i Y, może mieć współrzędne kontrolki, w której nie ma dobrego miejsca do wyświetlenia tekstu. Każdy host programu Power Fx kontroluje sposób, w jaki błędy są ostatecznie wyświetlane użytkownikowi końcowemu, oraz określa, w jakim stopniu twórca może kontrolować proces. W usłudze Power Apps jest wyświetlany baner błędu, a procedura App.OnError służy do kontrolowania sposobu raportowania błędu.
Należy zwrócić uwagę, że procedura App.OnError nie może zastąpić błędu tak samo jak funkcja IfError. W momencie wykonywania procedury App.OnError błąd już wystąpił i wynik został propagowany w innych formułach. App.OnError kontroluje tylko sposób zgłaszania błędu do użytkownika końcowego i udostępnia punkt zaczepienia dla twórcy, aby w razie potrzeby zarejestrować błąd.
Zmienne zakresu FirstError i AllErrors zawierają informacje kontekstowe o błędzie lub błędach. Dostarcza to informacje o rodzaju błędu, miejscu jego pochodzenia i miejscu wystąpienia.
Zatrzymanie po błędzie
Formuły zachowania obsługują podejmowanie akcji, modyfikowanie baz danych i zmianę stanu. Te formuły umożliwiają wykonanie więcej niż jednej akcji w sekwencji przy użyciu operatora łańcucha ;
(lub ;;
w zależności od ustawień regionalnych).
W tym przypadku na przykład kontrolka siatki pokazuje, co zawiera tabela T
. Każdy przycisk powoduje zmianę stanu tabeli przy użyciu dwóch wywołań Patch:
W formule zachowań łańcuchowych akcje nie są zatrzymywane po pierwszym błędzie. Zmodyfikujmy ten przykład, aby przekazać nieprawidłowy numer indeksu w pierwszym wywołaniu Patch. Drugie wywołanie Patch jest kontynuowane mimo tego wcześniejszego błędu. Pierwszy błąd jest zgłaszany do użytkownika końcowego i jest wyświetlany jako błąd w programie Studio w kontrolce:
IfError może służyć do zatrzymywania wykonywania po wystąpieniu błędu. Podobnie jak w funkcji If, trzeci argument tej funkcji umożliwia umieszczanie akcji, które powinny być wykonywane tylko wtedy, gdy nie będzie żadnych błędów:
Jeśli podczas jednej z iteracji funkcji ForAll wystąpi błąd, reszta iteracji nie zostanie zatrzymana. ForAll jest przeznaczony do wykonywania każdej iteracji niezależnie, co pozwala na wykonywanie równoległe. Po zakończeniu działania funkcji ForAll zostanie zwrócony błąd, który zawiera wszystkie napotkane błędy (przez zbadanie opcji AllErrors w funkcji IfError lub App.OnError).
Na przykład następująca formuła spowoduje, że funkcja ForAll zwróci dwa błędy (dla dzielenia przez zero dla Value
o wartości 0, dwa razy), a funkcja Collection
będzie mieć trzy rekordy (w sytuacji, gdy Value
ma wartość inną niż 0): [1, 2, 3]
.
Clear( Collection );
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );
Praca z wieloma błędami
Ponieważ formuła zachowania może wykonać więcej niż jedną akcję, może też wystąpić wiele błędów.
Domyślnie pierwszy błąd jest zgłaszany użytkownikowi końcowemu. W tym przykładzie oba wywołania Patch nie powiodą się, w tym drugie z błędem dzielenia przez zero. Użytkownikowi jest wyświetlany tylko pierwszy błąd (informacje o indeksie):
Funkcje IfError i App.OnError mogą uzyskać dostęp do wszystkich błędów występujących ze zmienną zakresu AllErrors. W tym przypadku można ustawić tę zmienną globalną i sprawdzić oba napotkane błędy. Występują one w tabeli w tej samej kolejności, w której wystąpiły:
W formułach innych niż dotyczące zachowań można również zwrócić wiele błędów. Na przykład użycie funkcji Patch z partią rekordów w celu aktualizacji może zwrócić wiele błędów, po jednym dla każdego rekordu, który kończy się niepowodzeniem.
Błędy w tabelach
Jak już pokazano, błędy mogą być przechowywane w zmiennych. Błędy mogą także znaleźć się w strukturach danych, takich jak tabele. Jest to ważne, aby błąd w jednym rekordzie nie spowodował unieważnienia całej tabeli.
Rozważmy na przykład kontrolkę tej tabeli danych w usłudze Power Apps:
Podczas obliczania w funkcji AddColumns wystąpił błąd dzielenia przez zero dla jednej z wartości. W przypadku tego jednego rekordu kolumna Reciprocal zawiera wartość błędu (dzielenie przez zero), ale w innych rekordach nie i taka sytuacja jest w porządku. IsError( Index( output, 2 ) )
Zwraca wartość false i IsError( Index( output, 2 ).Value )
zwraca wartość true.
Jeśli podczas filtrowania tabeli wystąpi błąd, cały rekord jest błędem, ale w wyniku wciąż jest zwracany, dzięki czemu użytkownik końcowy wie, że coś się stało i wystąpił błąd.
Zapoznaj się z tym przykładem. Tutaj w pierwotnej tabeli nie ma błędów, ale działanie filtrowania powoduje utworzenie błędu za każdym razem, gdy Wartość jest równa 0:
Wartości -5 i -3 są poprawnie odfiltrowane. Wartości 0 powodują błąd w przetwarzaniu filtru, przez co niejasne jest, czy rekord powinien zostać uwzględniony w wyniku, czy nie. Aby zmaksymalizować widoczność dla użytkowników końcowych i pomóc twórcom w debugowaniu, w miejsce oryginalnego rekord uwzględniamy rekord z błędem. W tym przypadku funkcja IsError( Index( output, 2 ) )
zwraca wartość prawda.
Błędy źródła danych
Funkcje, które modyfikują dane w źródłach danych, takie jak Patch, Collect, Remove, RemoveIf, Update, UpdateIf i SubmitForm, zgłaszają błędy na dwa sposoby:
- Każda z tych funkcji zwraca wartość błędu w wyniku operacji. Błędy można wykrywać za pomocą funkcji IsError oraz zastępować lub pomijać je w zwykły sposób za pomocą funkcji IfError i App.OnError.
- Po operacji funkcja Errors zwraca również błędy z poprzednich operacji. Może być to przydatne do wyświetlania komunikatu o błędzie na ekranie formularza bez konieczności przechwytywania błędu w zmiennej stanu.
Na przykład ta formuła będzie sprawdzać, czy wystąpił błąd w funkcji Collect, i wyświetlać niestandardowe komunikaty o błędzie:
IfError( Collect( Names, { Name: "duplicate" } ),
Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )
Funkcja Errors zwraca również informacje o błędach z przeszłości podczas operacji środowiska uruchomieniowego. Może ona być przydatna do wyświetlania błędu na ekranie formularza bez konieczności przechwytywania błędu w zmiennej stanu.
Ponowne zgłaszanie błędów
Czasami są oczekiwane niektóre potencjalne błędy i można je zignorować. Jeśli wewnątrz funkcji IfError i App.OnError zostanie wykryty błąd, który należy przekazać do następnej procedury obsługi na wyższym poziomie, można go ponownie zgłosić przy użyciu Error( AllErrors )
.
Tworzenie własnych błędów
Za pomocą funkcji Error można również tworzyć własne błędy.
W przypadku tworzenia własnych błędów zaleca się użycie wartości powyżej 1000 w celu uniknięcia potencjalnych konfliktów z przyszłymi wartościami błędów systemowych.
Wartości wyliczenia ErrorKind
Wyliczenie ErrorKind | Wartość | opis |
---|---|---|
AnalysisError | 18 | Błąd systemowy. Wystąpił problem z analizą kompilatora. |
BadLanguageCode | 14 | Został użyty nieprawidłowy lub nierozpoznany kod języka. |
BadRegex | 15 | Nieprawidłowe wyrażenie regularne. Sprawdź składnię używaną przez funkcje IsMatch, Match lub MatchAll. |
Konflikt | 6 | Uaktualniany rekord został już zmieniony u źródła i konflikt musi zostać rozwiązany. Typowe rozwiązanie to zapisanie wszystkich lokalnych zmian, odświeżenie rekordu i ponowne zastosowanie zmian. |
ConstraintViolated | 8 | Rekord otrzymał negatywny wynik sprawdzania ograniczeń na serwerze. |
CreatePermission | 3 | Użytkownik nie ma uprawnienia do tworzenia rekordów dla źródła danych. Na przykład została wywołana funkcja Collect. |
DeletePermissions | 5 | Użytkownik nie ma uprawnienia do usuwania rekordów dla źródła danych. Na przykład została wywołana funkcja Remove. |
Div0 | 13 | Dzielenie przez zero. |
EditPermissions | 100 | Użytkownik nie ma uprawnienia do tworzenia rekordów dla źródła danych. Na przykład została wywołana funkcja Patch. |
GeneratedValue | 9 | Wartość została błędnie przekazana na serwer dla pola, które jest automatycznie obliczane przez serwer. |
InvalidFunctionUsage | 16 | Nieprawidłowe użycie funkcji. Często jeden lub kilka argumentów funkcji jest niepoprawnych lub używanych w nieprawidłowy sposób. |
FileNotFound | 17 | Nie można odnaleźć magazynu SaveData. |
InsufficientMemory | 21 | Brak pamięci lub miejsca w urządzeniu do wykonania operacji. |
InvalidArgument | 25 | Do funkcji został przekazany nieprawidłowy argument. |
Wewnętrznie | 26 | Błąd systemowy. Wystąpił problem wewnętrzny z jedną z funkcji. |
MissingRequired | 2 | Brakuje wymaganego pola rekordu. |
Sieć | 23 | Wystąpił problem z komunikacją w sieci. |
None | 0 | Błąd systemowy. Nie ma błędu. |
Nie dotyczy | 27 | Brak dostępnych wartości. Umożliwia odróżnienie wartości pustej, którą można traktować jako zero w obliczeniach numerycznych, od wartości pustych, które powinny być oznaczane jako potencjalny problem, jeśli ta wartość jest używana. |
Nie znaleziono | 7 | Nie można odnaleźć rekordu. Można na przykład zmodyfikować rekord w funkcji Patch. |
NotSupported | 20 | Ten odtwarzacz lub urządzenie nie obsługuje tej operacji. |
Liczbowe | 24 | Funkcja numeryczna została użyta w sposób niepoprawny. Na przykład Sqrt z wartością -1. |
QuoteExceeded | 22 | Przekroczono limit przydziału magazynu. |
ReadOnlyValue | 10 | Kolumna jest tylko do odczytu i nie można jej modyfikować. |
ReadPermission | 19 | Użytkownik nie ma uprawnienia do odczytywania rekordów dla źródła danych. |
Synchronizacja | 1 | Źródło danych zgłosiło błąd. Więcej informacji można znaleźć w kolumnie Wiadomość. |
Nieznane | 12 | Wystąpił błąd nieznanego typu. |
Sprawdzanie poprawności | 11 | Rekord nie otrzymał pozytywnego wyniku walidacji. |