Spec-Zone.ru › Phoenix

Обработка ошибок и исключений

Исходный код

Как и в любом другом коде Elixir, исключения могут возникать на протяжении жизненного цикла LiveView. На этой странице описано, как LiveView обрабатывает ошибки на разных этапах.

Ожидаемые сценарии

В этом разделе мы поговорим об ошибках, которые могут возникнуть в вашем приложении. Например, ожидаемо, что пользователь может заполнить форму некорректными данными. В LiveView мы обычно обрабатываем такие ситуации, сохраняя состояние формы в assigns LiveView и отображая клиенту соответствующее сообщение об ошибке.

Для этого мы также можем использовать сообщения flash. Например, представьте, что у вас есть страница для управления всеми «Участниками команды» в организации. Однако если в организации остался только один участник, ему не следует разрешать выходить из неё. Эту ситуацию можно обработать с помощью flash-сообщений:

if MyApp.Org.leave(socket.assigns.current_org, member) do
  {:noreply, socket}
else
  {:noreply, put_flash(socket, :error, "last member cannot leave organization")}
end

Однако можно возразить, что если последний участник организации не может выйти из неё, то, возможно, лучше вообще не показывать кнопку «Выйти» в интерфейсе, когда в организации остался только один участник.

Если кнопка не отображается в интерфейсе, попытка выполнить действие «выйти», когда в организации остался только один участник, является неожиданным сценарием. Это означает, что приведённый выше код можно переписать так:

true = MyApp.Org.leave(socket.assigns.current_org, member)
{:noreply, socket}

Если leave не возвращает true, Elixir вызовет исключение MatchError. Или можно предоставить функцию leave!, которая вызывает определённое исключение:

MyApp.Org.leave!(socket.assigns.current_org, member)
{:noreply, socket}

Но что произойдёт с LiveView в случае исключения? Давайте поговорим о неожиданных сценариях.

Неожиданные сценарии

Разработчики Elixir обычно пишут код с явными проверками. Это означает, что если мы ожидаем, что leave всегда возвращает true, мы можем явно сопоставить результат с образцом, как сделали выше:

true = MyApp.Org.leave(socket.assigns.current_org, member)
{:noreply, socket}

Если leave завершается неудачей и возвращает false, возникает исключение. Разработчики Elixir часто используют исключения для обработки неожиданных сценариев в приложениях Phoenix.

Например, если вы создаёте приложение, в котором пользователь может состоять в одной или нескольких организациях, при открытии страницы организации можно проверить, есть ли у пользователя к ней доступ:

organizations_query = Ecto.assoc(socket.assigns.current_user, :organizations)
Repo.get!(organizations_query, params["org_id"])

Приведённый выше код формирует запрос, который возвращает все организации, в которых состоит текущий пользователь, а затем проверяет, что указанная org_id принадлежит этому пользователю. Если такой org_id нет или у пользователя нет к ней доступа, Repo.get! вызовет исключение Ecto.NoResultsError.

При обычном запросе контроллера это исключение преобразуется в исключение 404 и отображается как пользовательская страница ошибки, как описано здесь. LiveView реагирует на исключения тремя разными способами — в зависимости от этапа жизненного цикла.

Исключения при HTTP-монтировании

При первом обращении к LiveView на сервер отправляется обычный HTTP-запрос, который обрабатывается LiveView. Вызывается callback mount, после чего отображается страница. Любое исключение на этом этапе перехватывается, записывается в журнал и преобразуется в страницу исключения средствами Phoenix error views — точно так же, как и при работе с контроллерами.

Исключения при монтировании подключённого LiveView

Если первоначальный HTTP-запрос выполнен успешно, LiveView подключается к серверу через соединение с сохранением состояния, обычно WebSocket. При этом на сервере запускается долгоживущий лёгкий процесс Elixir, который вызывает callback mount и отображает обновлённую версию страницы.

Исключение на этом этапе приведёт к сбою процесса LiveView, о котором будет сделана запись в журнале. Заметив сбой, клиент полностью перезагрузит страницу. В результате mount будет вызван повторно при обычном HTTP-запросе (как в сценарии, описанном в предыдущем подразделе).

Иными словами, при ошибках LiveView перезагрузит страницу, и она завершится сбоем так, как если бы LiveView изначально не участвовал в её отображении.

Исключения после монтирования подключённого LiveView

После монтирования и подключения LiveView любая ошибка приведёт к сбою процесса LiveView, о котором будет сделана запись в журнале. Заметив ошибку, клиент повторно смонтирует LiveView через соединение с сохранением состояния, не перезагружая страницу (как в сценарии, описанном в предыдущем подразделе). Если повторное монтирование пройдёт успешно, LiveView вернётся в рабочее состояние, обновит страницу и покажет пользователю актуальную информацию.

Например, предположим, что два пользователя пытаются одновременно выйти из организации. В этом случае оба видят кнопку «Выйти», но вызов нашей функции leave завершится успешно только для одного из них:

true = MyApp.Org.leave(socket.assigns.current_org, member)
{:noreply, socket}

При возникновении исключения клиент повторно смонтирует LiveView. После повторного монтирования код обнаружит, что в организации остался только один пользователь, и больше не будет показывать кнопку «Выйти». Иными словами, повторное монтирование часто обновляет состояние страницы, позволяя автоматически обрабатывать исключения.

Обратите внимание: решать, проверять ли результат функции leave условием if или просто утверждать, что она возвращает true, — исключительно вам. Если вероятность того, что все одновременно выйдут из организации, невелика, можно считать такую ситуацию неожиданной. Другим разработчикам, однако, будет комфортнее явно обрабатывать подобные случаи. В обоих случаях LiveView поможет вам.

Наконец, если LiveView завершится сбоем, его текущее состояние будет потеряно. К счастью, в LiveView есть ряд механизмов и рекомендаций, которые помогут при повторном подключении показать пользователю ту же страницу, что и до сбоя. Дополнительные сведения см. в руководстве «Развёртывание и восстановление».

← Предыдущая страница Развёртывание и восстановление
Следующая страница → Gettext для интернационализации

Пакет Hex Предпросмотр Hex (текущий файл) Просмотреть llms.txt Скачать версию ePub

Создано с помощью ExDoc (v0.40.3) для языка программирования Elixir

© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix-live-view.hexdocs.pm/error-handling.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API