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 udostępnia również typowe punkty 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.

  1. Utwórz nowy ekran w aplikacji kanwy Power Apps.
  2. Wstaw kontrolkę TextInput. Zostanie ona domyślnie nazwana TextInput1.
  3. Wstaw kontrolkę Label.
  4. Ustaw właściwość Text kontrolki Label na formułę
1/Value( TextInput1.Text )

Banner błędu wyświetlany z wartością „nie można przekonwertować wartości na liczbę” formantu text input zawierającego „Wprowadzany tekst”

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()

Banner błędu wyświetlany z „podziałem przez zero”

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() )

Nie jest wyświetlany banner błędu, błąd z powodu pustej wartości został zastąpiony na pusty

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 ) ) )

Nie jest wyświetlany banner błędu, błąd z powodu podziału na zera został zastąpiony pustym, w przeciwnym razie błąd jest ponownie zgłaszany

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.

Wyświetlany jest brak odpowiedzi i brak banneru błędu

Po wpisaniu 4 jest oczekiwany wynik 0,25:

Wyświetlane jest 0,25 i brak banneru błędu

Jeśli wpiszemy coś niedozwolonego, np. hello, zobaczymy baner błędu:

brak wyświetlanych wartości i banner błędu widocznych dla możliwości konwersji „witaj” na liczbę

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:

  1. 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" )
    
    brak banneru błędu i zamiast tego #Error jest wyświetlany w wyniku
  2. 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!:

Arkusz kalkulacyjny programu Excel o wartościach A1=1/0 i #DIV/0! widoczne w komórce

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:

Arkusz kalkulacyjny programu Excel o wartościach A2=A1*2 i #DIV/0! widoczne w komórce

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:

Banner błędu przedstawiający nieprawidłową operację: dzielenie przez zero

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:

Brak błędu widocznego w drugiej kontrolce label

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:

Brak banneru błędu wyświetlanego z funkcją Jeśli we właściwości etykiety Text

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:

Brak banneru błędu wyświetlanego z działaniem funkcji Ustaw w App.OnStart

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:

Banner błędu wyświetlany z formantem label odwołującym się do zmiennej x

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 jedynie sposób raportowania błędu do użytkownika końcowego i umożliwia twórcy rejestrowanie błędu w razie potrzeby.

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:

Animacja pokazująca dwa rekordy w tabeli T, która jest aktualizowana o losowe liczby po każdym kliknięciu przycisku

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:

Animacja przedstawiająca tylko drugi rekord w tabeli T, która jest aktualizowana o losowe liczby po każdym kliknięciu przycisku, pierwszy rekord z wynikowym błędem

IfError może zatrzymać wykonanie po błędzie. 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:

Animacja przedstawiająca brak zmian w którymkolwiek z rekordów w tabeli T, ponieważ ifError uniemożliwia ukończenie drugiej operacji po błędzie

Jeśli podczas jednej z iteracji funkcji ForAll wystąpi błąd, reszta iteracji nie zostanie zatrzymana. ForAll służy do wykonywania poszczególnych operacji niezależnie, co umożliwia 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):

Pierwszy błąd indeksu wyświetlany na bannerze błędu, drugi błąd nie jest raportowany

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:

Rejestrowanie błędów w zmiennej globalnej PatchErrors, gdzie widać, że oba błędy występują

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:

Tabela danych pokazująca błąd w polu Obustronnie dla danych wejściowych 0, co powoduje podział według błędu zerowego

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ść fałsz, a IsError( Index( output, 2 ).Value ) zwraca wartość prawda.

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:

Tabela danych pokazująca błędy w przypadku dwóch rekordów, których nie można przetworzyć według kryteriów filtrowania

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.