Поділитися через


Обробка помилок

Нотатка

Поведінка, описана в цій статті, доступна лише в разі ввімкнення експериментальної функції Керування помилками на рівні формули в меню Параметри>Заплановані функції>Підготовча версія. Додаткові відомості: Керування ввімкненням функцій

Помилки трапляються. Мережі дають збій, обсяг сховища заповнюється, з’являються неочікувані значення. Важливо, щоб логіка продовжувала працювати правильно в разі виникнення потенційних проблем.

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

Як розробник програми ви може керувати помилками в програмі.

  • Виявлення й обробка помилок. Якщо є підозра, що може виникнути помилка, можна написати формули програми, щоб виявити умову помилки та повторити операцію. Кінцевий користувач не повинен турбуватися через те, що сталася помилка, оскільки розробник врахував таку можливість. Це робиться за допомогою функцій IfError, IsError і IsErrorBlank у формулі.
  • Звітування про помилку. Якщо помилка не оброблюється у формулі, де вона сталася, то вона передається до обробника App.OnError. Тут помилку більше на можна замінити, оскільки вона вже сталася й є частиною обчислень формули. Але за допомогою App.OnError можна керувати способами повідомлення про помилку кінцевому користувачу, включно з повним блокуванням звітування про помилки. App.OnError також надає загальну контрольну точку для звітування про помилки в усій програмі.
  • Створення та повторне генерування помилки. Зрештою, можна виявити умову помилки за допомогою власної логіки, тобто умову, що відповідає програмі. Щоб створити настроювані помилки, скористайтеся функцією Помилка. Функція Помилка також використовується для того, щоб повторно генерувати помилку, після того як її було докладно перевірено в IfError або App.OnError.

Початок роботи

Розглянемо простий приклад.

  1. Створіть новий екран у компонованій програмі Power Apps.
  2. Вставте елемент керування Введення тексту. За замовчуванням буде вибрано ім’я TextInput1.
  3. Вставте елемент керування Надпис.
  4. Установіть для властивості Текст елемента керування Надпис таку формулу
1/Value( TextInput1.Text )

Відображається банер помилки з повідомленням «Значення не можна перетворити на число» для елемента керування введенням тексту, що містить «Введення тексту»

Сталася помилка, оскільки текст за замовчуванням елемента керування TextInput є "Text input", який не можна перетворити на число. За замовчуванням це непогано: кінцевий користувач отримає сповіщення про те, що в програмі щось працює не так, як очікувалося.

Очевидно, ми не хочемо, щоб повідомлення про помилку вітало користувача щоразу під час запуску програми. У будь-якому разі "Text input" не є правильним значенням за замовчуванням для поля введення тексту. Щоб це виправити, змінимо властивість Default елемента керування TextInput на:

Blank()

Відображається банер помилки з написом

Хм, тепер у нас з’явилася інша помилка. Математичні операції зі значенням blank, як-от ділення, призведе пусте значення до нуля. І це призводить до помилки під час ділення на нуль. Щоб це виправити, ми повинні вирішити, яка поведінка є правильною для такої ситуації в цій програмі. Відповіддю може бути відображення blank, коли введення тексту є blank. Для цього перенесіть формулу за допомогою функції IfError.

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

Банер помилки не відображається, помилку через порожнє значення замінено на порожнє

Тепер помилку замінено на припустиме значення, і банер із помилкою зник. Але, можливо, ми помилилися, використовувана функція ifError охоплює всі помилки, включно з введенням неправильних значень, як-от "hello". Це можна вирішити, налаштувавши функцію ifError так, щоб вона оброблювала лише сценарій ділення на нуль і повторно генерувала всі інші помилки:

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

Банер помилки не відображається, помилка, пов’язана саме з діленням на нуль, була замінена пробілом, інакше помилка викидається повторно

Отже, запустимо програму та спробуємо інші значення.

Як і під час запуску програми, якщо значення немає, відповідь не відображається, оскільки стандартне значення є blank, але повідомлення про помилку не відображатиметься, оскільки ifError замінює помилку ділення на нуль.

Відповідь не відображається, банер з помилкою

Якщо ввести значення 4, буде отримано очікуваний результат 0,25:

Відображається 0.25 і немає банера з помилкою

І якщо ввести щось неприпустиме, наприклад hello, відобразиться банер із помилкою:

Не відображається значення та відображається банер помилки через неможливість конвертувати

Це простий вступний приклад. Обробку помилок можна виконувати різними способами залежно від потреб програми:

  1. Замість банеру з помилкою можна було відобразити «#Error» в елементі керування надписом із формулою. Щоб підтримувати типи замін, сумісні з першим аргументом IfError, необхідно явно перетворити числовий результат на текстовий рядок із функцією Текст.
    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 ) поверне помилку «Ділення на нуль», оскільки внутрішня помилка проходить через функцію Текст та функцію Mid:

Банер помилки з неправильною операцією: ділення на нуль

Загалом помилки не надходять через властивості елемента керування Power Apps. Доповнимо попередній приклад додатковим елементом керування, який відображається, якщо властивість першого надпису Text є станом помилки:

Помилка не відображається на елементі керування другою міткою

Добре, що помилки не проходять через елемент керування, оскільки система виявлятиме помилки під час введення для всіх властивостей елементів керування. Помилку не буде втрачено.

Більшість функцій і операторів слідують правилу «помилка на вході, помилка на виході», але існують певні винятки. Функції IsError, IsErrorOrBlank, IfError призначено для роботи з помилками, щоб вони не повертали помилку, навіть якщо вона передається до них.

Виявлення помилок

Помилки не виявлятимуться, доки їхнє значення не використовується.

Як наслідок, функції If і Select можуть також не повертати помилку, якщо її передано. Розглянемо формулу If( false, 1/0, 3 ). У цій формулі є помилка ділення на нуль, але оскільки If не приймає відгалуження через false, Power Fx і Power Apps не повідомляють про помилку:

Банер помилки не відображається з функцією if у властивості Text (Текст)

Якщо використати функцію Set з помилкою, про помилку не буде повідомлено під час внесення її до змінної. Наприклад, у Power Apps в App.OnStart є формула, яка поміщає помилку ділення на нуль у змінну x:

Банер помилки не відображається під час виклику функції в App.OnStart

Про помилку не повідомлено, оскільки відсутнє посилання на x. Проте коли ми додамо елемент керування надписом і встановимо для його властивості Текст значення x, відобразиться повідомлення про помилку:

Відображається банер помилки з елементом керування міткою, що посилається на змінну x

Виявляти помилки у формулі можна за допомогою функцій IfError, IsError і IsErrorBlank. За допомогою цих функцій можна повертати альтернативне значення, вживати альтернативні дії або змінювати помилку, перш ніж її буде виявлено й зареєстровано.

Звітування про помилки

Після виявлення помилки, наступний крок — повідомити кінцевому користувачу про помилку.

На відміну від Excel, не завжди є зручне місце для відображення результату помилки, оскільки результат формули може задіювати властивість, як-от координати X і Y елемента керування, для якої немає зручного місця для відображення тексту. Кожний вузол Power Fx керує відображенням помилок для кінцевого користувача й степенем контролю розробника над цим процесом. У Power Apps відображається банер із помилкою, а App. OnError використовується для керування способом звітування про помилку.

Важливо зазначити, що App.OnError не може замінити помилку так само, як це робить ifError. На момент виконання App.OnError помилка вже відбулася, і результат походить через інші формули. App.OnError лише контролює спосіб звітування про помилку кінцевому користувачу та дає змогу розробнику записати помилку за потреби.

Область застосування змінних FirstError і AllErrors містить контекстну інформацію про помилки або самі помилки. Вона надає відомості про типи помилок, джерело помилки та місце її виявлення.

Зупинка після помилки

Формули для поведінки сприяють виконанню дії, редагуванню баз даних і зміненню стану. Ці формули дають змогу послідовно виконувати кілька дій за допомогою ланцюжкового оператора ; (або ;; залежно від локалізації).

У такому разі, наприклад, елемент керування сіткою показує дані в таблиці T. Кожна кнопка змінює стан у цій таблиці двома викликами Patch:

Анімація, що показує, що два записи в таблиці T оновлюються випадковими числами після кожного натискання кнопки

У формулі з ланцюжковою поведінкою дії не зупиняються після першої помилки. Змінемо наш приклад і передамо недійсний індекс у перший виклик Patch. Другий 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.

Таблиця даних, що показує похибку для поля Reciprocal для вхідних даних, рівних 0, що призводить до похибки ділення на нуль

В обчисленні AddColumns сталася помилка ділення на нуль для одного із значень. Для цього запису в стовпці Reciprocal існує значення помилки (ділення на нуль), але інші записи не містять цієї помилки й є допустимими. IsError( Index( output, 2 ) ) повертає значення «false», а IsError( Index( output, 2 ).Value ) повертає значення «true».

Якщо помилка сталася під час фільтрування таблиці, увесь запис є помилкою, але все одно повертається в результаті, щоб кінцевий користувач знав, що сталася помилка.

Подивіться цей приклад. Тут вихідна таблиця не містить помилок, але дія фільтрування створює помилку щоразу, коли Значення дорівнює 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 Немає доступного значення. Корисно відрізняти значення blank, яке можна розглядати як нуль у числових обчисленнях, від пустих значень, які слід позначити як можливу проблему, якщо значення використовується.
NotFound 7 Не вдалося знайти запис. Наприклад, запис, який потрібно змінити в функції Patch.
NotSupported 20 Операція не підтримується цим програвачем або пристроєм.
Числовий 24 Числова функція використовувалася неправильно. Наприклад, Sqrt з -1.
QuoteExceeded 22 Перевищено квоту сховища.
ReadOnlyValue 10 Стовпець доступний лише для читання, і його не можна змінити.
ReadPermission 19 Користувач не має дозволу на читання записів для джерела даних.
Синхронізація 1 Джерело даних повідомило про помилку. Додаткові відомості див. в стовпці «Message».
Невідомо 12 Сталася помилка невідомого типу.
Перевірка 11 Запис не пройшов перевірку.