Подтвердить что ты не робот

RxSwift - неправильная концепция

Я очень новичок в RxSwift, и я пытаюсь начать с простого экрана входа. Таким образом, у меня есть 2 текстовых поля и кнопка входа в систему, которая привязывается к PublishSubject, поэтому каждый раз, когда я нажимаю кнопку, я отправляю сетевой запрос для выполнения проверки подлинности.

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

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

Здесь первая версия, которая работает (запрос каждый раз, когда я касаюсь кнопки):

let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) }
self.signIn = signInTaps
    .asDriver(onErrorJustReturn: ())
    .withLatestFrom(credentials)
    .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>>
        return provider.request(.Authenticate(email: email, password: password))
            .filterSuccessfulStatusCodes()
            .mapObject(AuthenticateResponse)
            .map { element -> Result<AuthenticateResponse, APIError> in
                return .Success(element)
            }
            .asDriver { error in
                let e = APIError.fromError(error)
                return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e))
            }
            .debug()
    }

А вот тот, который не работает (запрос срабатывает только при первом щелчке):

let credentials = Observable.combineLatest(email.asObservable(), password.asObservable()) { ($0, $1) }
self.signIn = signInTaps.asObservable()
    .withLatestFrom(c)
    .flatMapLatest { email, password in // returns Observable<AuthenticateResponse>
        return provider.request(.Authenticate(email: email, password: password))
            .filterSuccessfulStatusCodes()
            .mapObject(AuthenticateResponse)
    }
    .map { element -> Result<AuthenticateResponse, APIError> in // returns Observable<Result<AuthenticateResponse, APIError>>
        return .Success(element)
    }
    .asDriver { error in // returns Driver<Result<AuthenticateResponse, APIError>>
        let e = APIError.fromError(error)
        return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e))
    }
    .debug()

Для информации, здесь мое объявление свойств:

let email = Variable("")
let password = Variable("")
let signInTaps = PublishSubject<Void>()    
let signIn: Driver<Result<AuthenticateResponse, APIError>>
4b9b3361

Ответ 1

Позвольте сломать, что происходит в первом (поскольку они в основном одинаковы):

// 1.
let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) }
// 2.
self.signIn = signInTaps
    .asDriver(onErrorJustReturn: ())
    // 3.
    .withLatestFrom(credentials)
    // 4.
    .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>>
    return provider.request(.Authenticate(email: email, password: password))
        .filterSuccessfulStatusCodes()
        .mapObject(AuthenticateResponse)
        .map { element -> Result<AuthenticateResponse, APIError> in
            return .Success(element)
        }
        .asDriver { error in
            let e = APIError.fromError(error)
            return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e))
        }
        .debug()
}
  • Вы комбинируете последние сигналы от email и пароль и объединяете их в кортеж String s.
  • Это ваш сигнальный сигнал, составной из всех следующих сигналов.
  • Вы комбинируете последние результаты с credentials одним нажатием кнопки.
  • Каждый раз, когда кнопка используется, или эмиссия электронной почты/пароля, вы отменяете текущий сигнал и создаете новый, который делает вызов (используя Moya), фильтрует по успешным кодам состояния, сопоставляет объект и успешность обработки и ошибки.

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

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

let intDriver = sequenceOf(1, 2, 3, 4, 5, 6)
.asDriver(onErrorJustReturn: 1)
.map { $0 + 1 }
.filter { $0 < 5 }

совпадает с

let intObservable = sequenceOf(1, 2, 3, 4, 5, 6)
.observeOn(MainScheduler.sharedInstance)
.catchErrorJustReturn(1)
.map { $0 + 1 }
.filter { $0 < 5 }
.shareReplay(1)

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