Как бросить внутри замыкание в функции?

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

Я хотел, чтобы эта функция вызывала исключение, чтобы я мог просто использовать do catch для обработки ошибок или успешных случаев с разными типами.

Это моя функция:

func performRequest<T: Codable>(_ request: URLRequest, ofType: T.Type) throws -> T{
    URLSession.shared.dataTask(with: request) {(data, response, err) in
        if let err = err {throw err}
        if let response = response as? HTTPURLResponse {
            if response.statusCode != 200 {
                // Here I would return the value
            } else {
                // here I would throw the error
            }
        }
        }.resume()
}

Но в первой строке после URLSession.shared.dataTask я получил эту ошибку:

Invalid conversion from throwing function of type '(_, _, _) throws -> ()' to non-throwing function type '(Data?, URLResponse?, Error?) -> Void'

Я понимаю, что это потому, что я пытаюсь использовать функцию dataTask внутри, но мой вопрос в том, есть ли способ сделать это?

Вы не можете throw внутри обработчика завершения URLSession.shared.dataTask, потому что тип этого обработчика завершения уже определен, и он не является throws функцией.

matt 08.04.2019 22:21
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
156
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ваш звонок асинхронный. Вам необходимо вернуть данные в закрытии после получения данных. Для проверки успешности вызова вы можете использовать недавно введенный тип Result, так что вам не нужно throw

func performRequest<T: Codable>(_ request: URLRequest, completion: @escaping (Result<T, Error>) -> Void) {
    URLSession.shared.dataTask(with: request) { (data, response, err) in
        if let err = err {
            return completion(Result.failure(err))
        }
        if let response = response as? HTTPURLResponse {
            if response.statusCode == 200 { // 200 is code for OK btw
                return completion(Result.success(someValueOfTypeT))
            } else {
                return completion(Result.failure(yourError))
            }
        }
    }.resume()
}

Использование: (обратите внимание, что тип T можно вывести из объявления закрытия)

performRequest(someRequest) { (result: Result<SomeTypeConformsToCodable, Error>) in
    switch result {
    case .success(let value):
        // work with value
    case .failure(let err):
        print(err)
    }
}

Роберт Дреслер, большое спасибо за ваш ответ, я попробовал этот подход с использованием функции выбрасывания, потому что я вызываю эту функцию внутри другой функции, которая также принимает завершениеHandler с параметром типа Result, поэтому я подумал, что выбрасывание будет чище для чтения, как только я пришлось бы отправить результат внутри другого результата, теперь я понимаю, что это правильный путь... спасибо

Lucas 08.04.2019 22:32

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