Skip to content

RxSwift 文档:Error Handling

轩辕十四
Published date:

Table of contents

Open Table of contents

Error Handling - 错误处理


一旦序列里面产出了一个 error 事件,整个序列将被终止。RxSwift 主要有两种错误处理机制:

retryWhen

如果请求 JSON 失败,我们需要等待5秒后进行重试操作,重试4次如果全部失败则抛出错误:

// 请求 JSON 失败时,等待 5 秒后重试,
// 重试 4 次后仍然失败,就将错误抛出

let maxRetryCount = 4       // 最多重试 4 次
let retryDelay: Double = 5  // 重试延时 5 秒

rxJson
    .retryWhen { (rxError: Observable<Error>) -> Observable<Int> in
        return rxError.flatMapWithIndex { (error, index) -> Observable<Int> in
            guard index < maxRetryCount else {
                return Observable.error(error)
            }
            return Observable<Int>.timer(retryDelay, scheduler: MainScheduler.instance)
        }
    }
    .subscribe(...)
    .disposed(by: disposeBag)

我们用 flatMapWithIndex 这个操作符,因为它可以给我们提供错误的索引数 index。然后用这个索引数判断是否超过最大重试数,如果超过了,就将错误抛出。如果没有超过,就等待 5 秒后重试。

Result

如果我们只是想给用户一个错误提示,我们可以自定义一个 Result 枚举来进行处理:

// 自定义一个枚举类型 Result
public enum Result<T> {
    case success(T)
    case failure(Swift.Error)
}

例如如下的代码:

// 当用户点击更新按钮时,
// 就立即取出修改后的用户信息。
// 然后发起网络请求,进行更新操作,
// 一旦操作失败就提示用户失败原因

updateUserInfoButton.rx.tap
    .withLatestFrom(rxUserInfo)
    .flatMapLatest { userInfo -> Observable<Void> in
        return update(userInfo)
    }
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: {
        print("用户信息更新成功")
    }, onError: { error in
        print("用户信息更新失败: \(error.localizedDescription)")
    })
    .disposed(by: disposeBag)

修改之后:

updateUserInfoButton.rx.tap
    .withLatestFrom(rxUserInfo)
    .flatMapLatest { userInfo -> Observable<Result<Void>> in
        return update(userInfo)
            .map(Result.success)  // 转换成 Result
            .catchError { error in Observable.just(Result.failure(error)) }
    }
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { result in
        switch result {           // 处理 Result
        case .success:
            print("用户信息更新成功")
        case .failure(let error):
            print("用户信息更新失败: \(error.localizedDescription)")
        }
    })
    .disposed(by: disposeBag)

这样我们的错误事件被包装成了 Result.failure(Error) 元素。

Previous
RxSwift 文档:Observable
Next
RxSwift 文档:Observable 和 Observer