Отклонение возвращенного обещания внутри блока then

Скажем, у меня есть два обещания, которые я хочу совместить с when(resolved:), Я хочу отклонить обещание, если возникла проблема с первым обещанием, но решить иначе. По сути, это то, что я хочу сделать:

func personAndPetPromise() -> Promise<(Person, Pet?)> {
    let personPromise: Promise<Person> = ...
    let petPromise: Promise<Pet> = ...

    when(resolved: personPromise, petPromise).then { _ -> (Person, Pet?) in
        if let error = personPromise.error {
            return Promise(error: error) // syntax error
        }
        guard let person = personPromise.value else {
            return Promise(error: myError) // syntax error
        }
        return (person, petPromise.value)
    }
}

такой, что внешне я могу сделать что-то вроде этого:

personAndPetPromise().then { person, pet in
    doSomethingWith(person, pet)
}.catch { error in
    showError(error)
}

Проблема заключается в then { _ in блокировать в personAndPetPromise, Там нет никакого способа, которым этот метод может вернуть как Promise(error:) и (Person, Pet?),

Как еще я могу отклонить блок?

1 ответ

Проблема в том, что есть две перегрузки then функция:

public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> U) -> Promise<U>
public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> Promise<U>) -> Promise<U>

Первый body возвращает U и причины then возвращать Promise<U>,

Второй body возвращает Promise<U> и причины then возвращать Promise<U>,

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

Вот рабочая версия. Основное отличие в том, что я изменил -> (Person, Pet?) в -> Promise<(Person, Pet?)>:

func personAndPetPromise() -> Promise<(Person, Pet?)> {
    let personPromise: Promise<Person> = ...
    let petPromise: Promise<Pet> = ...

    when(resolved: personPromise, petPromise).then { _ -> Promise<(Person, Pet?)> in
        if let error = personPromise.error {
            return Promise(error: error)
        }
        guard let person = personPromise.value else {
            return Promise(error: myError)
        }
        return Promise(value: (person, petPromise.value))
    }
}

Другой способ сделать то же самое - выдать ошибку, а не пытаться ее вернуть:

func personAndPetPromise() -> Promise<(Person, Pet?)> {
    let personPromise: Promise<Person> = ...
    let petPromise: Promise<Pet> = ...

    when(resolved: personPromise, petPromise).then { _ -> (Person, Pet?) in
        if let error = personPromise.error {
            throw error
        }
        guard let person = personPromise.value else {
            throw myError
        }
        return (person, petPromise.value)
    }
}
Другие вопросы по тегам