Споделяне чрез


Грешка при обработването

Бележка

Поведението, което се описва в тази статия, е налично само когато функцията за преглед на управлението на грешки на ниво формула чрез Настройки>Бъдещи функции>Преглед е включена. Повече информация: Контролиране кои функции са активирани

Случват се грешки. Мрежите прекъсват, хранилището се запълва, постъпват неочаквани стойности. Важно е логиката ви да продължи да работи правилно при евентуални проблеми.

По подразбиране грешките преминават през формулите на приложението и се докладват на крайния потребител на приложението. По този начин крайният потребител знае, че се е случило нещо неочаквано, потенциално може сам да отстрани проблема с различен вход или може да докладва за проблема на собственика на приложението.

Като производител на приложения можете да поемете контрола върху грешките в приложението си:

  • Откриване и обработка на грешка. Ако има вероятност да възникне грешка, формулите на приложението могат да бъдат написани, за да открият състоянието на грешка и да опитат отново операцията. Крайният потребител не трябва да се притеснява, че е възникнала грешка, тъй като производителят е взел предвид тази възможност. Това се прави чрез функциите IfError, IsError и IsErrorOrBlank във формула.
  • Докладване на грешка. Ако грешка не е обработена във формулата, където е открита, грешката след това се извежда в балонче до манипулатора App.OnError. Тук грешката вече не може да бъде заменена, тъй като вече е възникнала и е част от изчисленията по формулата. Но можете да използвате App.OnError за да контролирате начина, по който грешката се съобщава на крайния потребител, включително потискане на докладването за грешка като цяло. App.OnError също така предоставя обща точка на блокиране за докладване на грешки в цялото приложение.
  • Създаване и повторно извеждане на грешка. И накрая, можете да откриете състояние на грешка с вашата собствена логика, условие, което е специфично за вашето приложение. Използвайте функцията Грешка за създаване на персонализирани грешки. Функцията Грешка се използва и за повторно изхвърляне на грешка, след като е била запитана в IfError или App.OnError.

Първи стъпки

Да започнем с един прост пример.

  1. Създаване на нов екран в приложение за платно на Power Apps.
  2. Вмъкване на контрол TextInput. По подразбиране ще бъде името TextInput1.
  3. Вмъкване на контрола Етикет.
  4. Задайте свойството Текст на контролата етикет на формулата
1/Value( TextInput1.Text )

Банер за грешка, показан с

Имаме грешка, защото текстът по подразбиране на TextInput контрола е "Text input", който не може да бъде преобразуван в число. По подразбиране това е нещо добро: крайният потребител ще получи известие, че нещо не работи според очакванията в приложението.

Очевидно е, че не искаме грешка да поздравява потребителя всеки път, когато стартира това приложение. Вероятно "Text input" все пак не е правилната настройка по подразбиране за полето за въвеждане на текст. За да поправим това, нека променим свойството Default на контролата TextInput на:

Blank()

Банер за грешка, показан с

Хм, сега имаме друга грешка. Математическите операции с празно, като например деление, ще принудително приведат празната стойност до нула. И това сега причинява грешка при деление на нула. За да коригираме това, трябва да решим какво е подходящото поведение за тази ситуация в това приложение. Отговорът може да бъде показване на празно когато въвеждането на текст е празно. Можем да постигнем това, като обвием нашата формула с функцията IfError:

IfError( 1/Value( TextInput1.Text ), Blank() )

Не се показва банер за грешка, грешка, дължаща се на празна стойност, е заменена с празна

Сега грешката е заменена с валидна стойност и банерът за грешка е изчезнал. Но може да сме превишили, IfError което използвахме покрива всички грешки, включително въвеждане на грешна стойност като като "hello". Можем да се справим с това, като настроим нашия IfError за обработка на делението на нула само с регистър и повторно хвърляне на всички други грешки:

IfError( 1/Value( TextInput1.Text ), 
         If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )

Не се показва банер за грешка, грешка, дължаща се конкретно на деление на нула, е заменена с празно, в противен случай грешката се хвърля отново

И така, нека стартираме нашето приложение и опитаме някои различни стойности.

Без никаква стойност, тъй като при стартиране на приложението няма показан отговор, тъй като стойността по подразбиране е празно, но също така не се показва грешка като IfError заменя делението с грешка нула.

Не се показва отговор и няма банер за грешка

Ако въведем 4, получаваме очаквания резултат от 0,25:

0.25 Показан и няма банер за грешка

И ако напишем нещо незаконно, като hello, тогава ще получим банер за грешка:

не се показва стойност и се показва банер за грешка за невъзможност за преобразуване на

Това е прост уводен пример. Обработката на грешки може да се извърши по много различни начини в зависимост от нуждите на приложението:

  1. Вместо банер за грешка, можехме да покажем "#Error" в контролата на етикета с формулата. За да поддържаме типовете замествания съвместими с първия аргумент на IfError трябва изрично да преобразуваме числения резултат в текстов низ с Text функция.
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    няма банер за грешка и вместо това #Error се показва като резултат
  2. Вместо да опаковаме този конкретен екземпляр с IfError можехме да напишем централизиран манипулатор App.OnError. Не можем да заменим показания низ с „#Error“, тъй като грешката вече се е случила и App.OnError се предоставя само за контрол на отчитането.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

Разпространение на грешки

Грешките протичат във формулите, подобно на това в Excel. Например в Excel, ако клетка A1 има формулата =1/0, тогава A1 ще покаже стойността на грешката #DIV0!:

Електронна таблица на Excel с A1=1/0 и #DIV/0! показан в клетката

Ако клетката A2 се отнася до A1 с формула като =A1*2, тогава грешката се разпространява и през тази формула:

Електронна таблица на Excel с A2=A1*2 и #DIV/0! показан в клетката

Грешката замества стойността, която иначе би била изчислена. Няма резултат за умножението в клетка A2, а само грешката от делението в A1.

Power Fx работи по същия начин. По принцип, ако грешката е предоставена като аргумент на функция или оператор, операцията няма да се осъществи и грешката при въвеждане ще премине като резултат от операцията. Например Mid( Text( 1/0 ), 1, 1 ) ще върне грешка при деление на нула, тъй като най-вътрешната грешка преминава през функцията Text и Mid функция:

Банер за грешка, показващ невалидна операция: деление на нула

По принцип грешките не преминават през Power Apps контролни свойства. Нека разширим предишния пример с допълнителна контрола, която показва дали свойството Text на първия етикет е състояние на грешка:

Не се показва грешка на втората контрола на етикета

Добре е грешките да не се разпространяват през контрола, защото системата ще наблюдава грешки на входа към всички свойства на контрола. Грешката няма да бъде загубена.

Повечето функции и оператори следват правилото "error in, error out", но има някои изключения. Функциите IsError, IsErrorOrBlank и IfError са предназначени за работа с грешки, така че може да не върнат грешка, дори ако такава бъде предадена в тях.

Наблюдаване на грешки

Грешките не се наблюдават, докато стойността им не се използва.

В резултат на това функциите If и Select може също да не върнат грешка, ако такава бъде предадена. Обмислете формулата If( false, 1/0, 3 ). В тази формула има грешка при деление на нула, но тъй като If не взема този клон поради false, Power Fx и Power Apps няма да докладват грешка:

Не се показва банер за грешка с функция If в свойството Текст на етикета

Използването на функцията Set с грешка няма да отчете грешка в момента, в който грешката е поставена в променливата. Например в Power Apps, ето формула в App.OnStart която поставя грешка при деление на нула в променливата x:

Не се показва банер за грешка с Задаване на извикване на функция в App.OnStart

Не се съобщава за грешка, тъй като x не се препраща. Въпреки това, в момента, в който добавим контрола на етикет и зададем свойството Text на x, грешката се показва:

Показан е банер за грешка с контрола на етикета, препращаща към променливата x

Можете да наблюдавате грешки във формула с функциите IfError, IsError и IsErrorOrBlank. С тези функции можете да върнете алтернативна стойност, да предприемете алтернативно действие или да промените грешката, преди да бъде наблюдавана и докладвана.

Докладване на грешки

След като бъде забелязана грешка, следващата стъпка е да докладвате грешката на крайния потребител.

За разлика от Excel, не винаги има удобно място за показване на резултат от грешка, тъй като резултатът от формула може да управлява свойство като X и Y координати на контрола, за която няма удобно място за показване на текст. Всеки Power Fx хост контролира как грешките в крайна сметка се показват на крайния потребител и колко контрол има създателят върху този процес. В Power Apps се показва банер за грешка и App.OnError се използва за контролиране на начина на докладване на грешката.

Важно е да се отбележи, че App.OnError не може да замени грешката по същия начин, по който IfError може. В момента, в който App.OnError се изпълнява, грешката вече се е случила и резултатът се е разпространил чрез други формули. App.OnError контролира само начина, по който грешката се докладва на крайния потребител и предоставя кука на производителя да регистрира грешката, ако желае.

Променливите за обхват FirstError и AllErrors предоставят контекстна информация за грешката или грешките. Това предоставя информация за вида на грешката и къде е възникнала грешката и къде е била наблюдавана.

Спиране след грешка

Формулите за поведение поддържат предприемане на действия, модифициране на бази данни и промяна на състоянието. Тези формули позволяват извършването на повече от едно действие в последователност, като се използва операторът ; chaining (или ;; в зависимост от локала).

В този случай, например, контролата на мрежата показва какво има в T таблицата. Всеки избор на бутон променя състоянието в тази таблица с две Patch извиквания:

Анимация, показваща двата записа в таблица T, които се актуализират с произволни числа след всяко щракване върху бутон

Във формулата за верижно поведение действията не спират след първата грешка. Нека модифицираме нашия пример, за да предадем невалиден индексен номер в първото Patch извикване. Вторият корекция продължава въпреки тази по-ранна грешка. Първата грешка се съобщава на крайния потребител и се показва като грешка в Studio на контролата:

Анимация, показваща само втория запис в таблица T, който се актуализира с произволни числа след всяко щракване върху бутон, като първият запис води до грешка

IfError може да се използва за спиране на изпълнението след грешка. Подобно на функцията If, третият аргумент на тази функция предоставя място за поставяне на действия, които трябва да бъдат изпълнени само ако няма грешка:

Анимация, която не показва промени в нито един запис в таблица T, тъй като IfError пречи на втората операция да завърши след грешка

Ако възникне грешка по време на една от итерациите на ForAll, останалите итерации няма да спрат. ForAll е проектиран да изпълнява всяка итерация независимо, което позволява паралелно изпълнение. Когато ForAll завърши, ще бъде върната грешка, която съдържа всички открити грешки (чрез изследване на AllErrors в IfError или App.OnError).

Например следната формула ще доведе до ForAll връщане на две грешки (за делението на нула за Value на 0, два пъти) и Collection ще има три записа (когато Value не е 0): [1, 2, 3].

Clear( Collection ); 
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );

Работа с множество грешки

Тъй като формулата за поведение може да изпълни повече от едно действие, тя също може да срещне повече от една грешка.

По подразбиране първата грешка се съобщава на крайния потребител. В този пример и двете извиквания на Patch ще бъдат неуспешни, второто с грешка при деление на нула. Само първата грешка (относно индекса) се показва на потребителя:

Първата грешка в индекса, показана в банер за грешка, втората грешка не се докладва

Функцията IfError и App.OnError могат да получат достъп до всички грешки, открити с AllErrors променлива на обхвата. В този случай можем да зададем това на глобална променлива и да разгледаме и двете открити грешки. Те се появяват в таблицата в същия ред, в който са били срещнати:

Улавяне на грешките в глобалната променлива PatchErrors, където можем да видим, че и двете грешки присъстват

Множество грешки могат да бъдат върнати и във формули за неповедение. Например, използването на функцията Patch с пакет от записи за актуализиране може да върне множество грешки, по една за всеки неуспешен запис.

Грешки в таблиците

Както видяхме по-рано, грешките могат да се съхраняват в променливи. Грешките могат да бъдат включени и в структури от данни, като например таблици. Това е важно, така че грешка в който и да е запис да не може да обезсили цялата таблица.

Например, разгледайте тази контрола на таблицата с данни в Power Apps:

Таблица с данни, показваща грешка за полето реципрочно за вход 0, което води до грешка при деление на нула

Изчислението в AddColumns е срещнало грешка при деление на нула за една от стойностите. За този един запис колоната Reciprocal има стойност на грешка (деление на нула), но другите записи нямат и са добре. IsError( Index( output, 2 ) ) Връща false и IsError( Index( output, 2 ).Value ) връща true.

Ако възникне грешка при филтриране на таблица, целият запис е грешка, но все още се връща в резултата, така че крайният потребител да знае, че нещо е имало и има проблем.

Вземете този пример. Тук оригиналната таблица няма грешки, но актът на филтриране създава грешка всеки път, когато Value е равно на 0:

Таблица с данни, показваща грешки за два записа, които не могат да бъдат обработени по критериите за филтриране

Стойностите -5 и -3 са правилно филтрирани. Стойностите 0 водят до грешка при обработката на филтъра и затова не е ясно дали записът трябва да бъде включен или не в резултата. За да увеличим максимално прозрачността за крайните потребители и да помогнем на производителите да отстраняват грешки, ние включваме запис за грешка на мястото на оригинала. В този случай IsError( Index( output, 2 ) ) връща true.

Грешки в източника на данни

Функциите, които променят данните в източниците на данни, като например Patch, Collect, Remove, RemoveIf, Update, UpdateIf и SubmitForm съобщават за грешки по два начина:

  • Всяка от тези функции ще върне стойност за грешка като резултат от операцията. Грешките могат да бъдат открити с IsError и заменени или потиснати с IfError и App. OnError както обикновено.
  • След операцията функцията Errors също ще върне грешките за предишни операции. Това може да е полезно за показване на съобщението за грешка на екрана на формуляра, без да е необходимо грешката да се записва в променлива на състоянието.

Например, тази формула ще провери за грешка от Collect и ще покаже персонализирано съобщение за грешка:

IfError( Collect( Names, { Name: "duplicate" } ),
         Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )

Функцията Errors също връща информация за минали грешки по време на операции по време на изпълнение. Може да бъде полезно за показване на грешка на екран на формуляр, без да е необходимо да се прихваща грешката в променлива на състоянието.

Прехвърляне на грешки

Понякога се очакват някои потенциални грешки и могат безопасно да бъдат игнорирани. В IfError и App.OnError, ако бъде открита грешка, която трябва да бъде предадена на следващия по-висок манипулатор, може да бъде прехвърлен с Error( AllErrors ).

Създаване на собствени грешки

Можете също да създавате свои собствени грешки с функцията Error.

Ако създавате свои собствени грешки, препоръчително е да използвате стойности над 1000, за да избегнете потенциални конфликти с бъдещи стойности на системни грешки.

Стойности на ErrorKind изброяване

ErrorKind изброяване Стойност Описание
AnalysisError 18 Системна грешка. Имаше проблем с анализа на компилатора.
BadLanguageCode 14 Използван е невалиден или неразпознат езиков код.
BadRegex 15 Невалиден регулярен израз. Проверете синтаксиса, използван с IsMatch, Match или MatchAll функции.
Конфликт 6 Записът, който се актуализира, вече е променен в източника и конфликтът трябва да бъде разрешен. Често срещано решение е да запазите всички локални промени, да опресните записа и да приложите отново промените.
ConstraintViolated 8 Записът не премина проверка за ограничение на сървъра.
CreatePermission 3 Потребителят няма разрешение за създаване на запис за източника на данни. Например беше извикана функцията Collect.
DeletePermissions 5 Потребителят няма разрешение за изтриване на запис за източника на данни. Например беше извикана функцията Remove.
Div0 13 Деление на нула.
EditPermissions 4 Потребителят няма разрешение за създаване на запис за източника на данни. Например беше извикана функцията Patch.
GeneratedValue 9 Стойност е погрешно предадена на сървъра за поле, което се изчислява автоматично от сървъра.
InvalidFunctionUsage 16 Неправилно използване на функция. Често един или повече от аргументите на функцията са неправилни или използвани по невалиден начин.
FileNotFound 17 Хранилището SaveData не може да бъде намерено.
InsufficientMemory 21 Няма достатъчно памет или място за съхранение на устройството за операцията.
InvalidArgument 25 Невалиден аргумент е предаден на функция.
Вътрешни 26 Системна грешка. Имаше вътрешен проблем с една от функциите.
MissingRequired 2 Липсваше задължително поле от запис.
Мрежа 23 Имаше проблем с мрежовите комуникации.
Нищо 0 Системна грешка. Няма грешка.
Неприложимо 27 Няма налична стойност. Полезно за разграничаване на празна стойност, която може да се третира като нула в числени изчисления от празни стойности, които трябва да бъдат маркирани като потенциален проблем, ако стойността се използва.
NotFound 7 Записът не може да бъде намерен. Например записът, който трябва да бъде модифициран във функцията Patch.
NotSupported 20 Операцията не се поддържа от този плейър или устройство.
Цифров 24 Числова функция е използвана по неправилен начин. Например Sqrt с -1.
QuoteExceeded 22 Превишена квота за съхранение.
ReadOnlyValue 10 Колоната е само за четене и не може да се променя.
ReadPermission 19 Потребителят няма разрешение за четене на запис за източника на данни.
Синхронизиране 1 Грешка е докладвана от източника на данни. Проверете графата Съобщение за повече информация.
Неизвестно 12 Възникна грешка, но от неизвестен вид.
Проверка 11 Записът не премина проверка за валидиране.