Как обрабатывать исключения из вызовов API в Unity и передавать их в пользовательский интерфейс?

Я пытаюсь понять, что делать с некоторыми ошибками в Unity, когда я вызываю API, и как распространить его на пользовательский интерфейс - где и как обрабатывать вещи. Я создал API-интерфейсы aspnet, но там я обычно использовал промежуточное программное обеспечение для обработки ошибок, чтобы поддерживать чистоту своих контроллеров.

Допустим, у нас есть такой код (я использую язык контроллера/репозитория, потому что это то, что я знаю).

  1. Кнопка пользовательского интерфейса запускает событие, подобное OnLoginButtonPressed.

  2. Класс AuthController реагирует на событие, вызывая метод входа в систему, а затем выполняя некоторую логику, когда приходит ответ, следующим образом:

    public async void Login(LoginModel input)
    {
     var result = await AuthRepo.instance.Login(input);
     app.token = result; 
     EventService.OnSuccessfulLogin();
    }
    
  3. Auth.Repo вызывает API и пытается вернуть класс Token (просто оболочка вокруг строки JWT).

     public async Task<Token> Login(LoginModel input)
     {
       string json = JsonConvert.SerializeObject(input);
       var request = UnityWebRequest.Post(app.baseURL + "authentication/login", json);
       request.SetRequestHeader("Content-Type", "application/json");
       request.SendWebRequest();
       while (!request.isDone)
       {
         await Task.Yield();
       }
    
       if (request.result == UnityWebRequest.Result.Success)
       {
         Token token = JsonConvert.DeserializeObject<Token>(request.downloadHandler.text);
         return token;
       }
       else
       {
         throw 
       }
    }
    

Так что без обработки исключений. Итак, я хочу попытаться сообщить пользователю, есть ли ошибка подключения, или они указали неверные данные и т. д. Я предполагаю, что должен добавить некоторую логику в AuthRepo, например:

    if (request.result == UnityWebRequest.Result.Success)
    {
        Token token = JsonConvert.DeserializeObject<Token>(request.downloadHandler.text);
        return token;
    }
    else if (request.result== UnityWebRequest.Result.ConnectionError)
    {
        throw new ConnectionException(request.error);
    }
    else if (request.result == UnityWebRequest.Result.DataProcessingError)
    {
        throw new BadRequestException(request.error);
    }
    else
    {
        throw new System.Exception(request.error);
    }

Кажется, что это много кода, и он окажется в каждом методе в каждом репо (если я не вытащу его в какой-нибудь вспомогательный метод?).... в любом случае, а затем в контроллере я бы сделал что-то вроде:

        try {
            var result = await AuthRepo.instance.Login(input);
            app.token = result; 
            EventService.OnSuccessfulLogin();
        }
        catch (ConnectionException ex)
        {
           EventService.OnConnectionError(ex.Message);
           //some UI object would listen for this event and show the connection error message.
        }
        catch (BadRequestException ex)
        {
           EventService.LoginFailedError(ex.Message);
        }
        finally
        {
           EventService.UnknownError(ex.Message);
        }

Это совершенно неправильный путь? Похоже, что код просто завалится обработкой исключений, или это правильный путь?

Я просмотрел несколько видеороликов на YouTube, которые, кажется, предполагают, что это правильно, но на самом деле они не показывают мой вариант использования (разговор с API), поэтому я просто пытаюсь быть уверенным.

Я не вижу ничего плохого в том, что в коде много обработки исключений ... Я бы предпочел абстрагировать это в EventService.HandleException и позволить службе решать в центральном месте, какие из них он знает, а какие Неизвестная ошибка => в вашем коде есть всегда будет один catch(Exception e) { EvntService.HandlException(e); } => таким образом, все известные исключения и возможные конкретные отображения находятся в одном центральном месте.. можно добавить дополнительные параметры/перегрузки в HandleException, если это необходимо, например. опуская сообщение об исключении, но передайте собственное сообщение и т. д.

derHugo 10.01.2023 15:11

кстати .. finally всегда выполняется .. также в случае успеха и ex в этом случае не существовало бы

derHugo 10.01.2023 15:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

поскольку UnityWebRequest.Result — это перечисление, здесь вы можете начать с оператора switch. Это не только чище, но и работает лучше.

Еще одна вещь, которую вы можете сделать, это создать абстрактный класс (например, APIException) и сделать его ответственным за создание правильных экземпляров исключений, предоставив ему какой-нибудь статический метод, такой как APIException FromUWRResult(UnityWebRequest.Result result).

Обработка исключений также может быть выполнена в APIException. Дайте ему абстрактный метод Handle() и реализуйте его соответствующим образом в каждом из производных классов.

Теперь ваш код будет выглядеть так:

var ex = APIException.FromUWRResult(request.result);
if (ex != null) {
    throw ex;
}

...

catch(APIException ex) {
    ex.Handle();
}

Другие вопросы по теме