KkevinK / Me

0 stars 0 forks source link

学习八 RxSwift+Moya+一些其他的第三方库 3 #12

Open KkevinK opened 3 years ago

KkevinK commented 3 years ago

查阅了一些资料后,决定对之前连续两次http的调用做出调整,即flatmap。

    func Deblocking(userName: String) {
        userProvider.rx.request(.getUserId(userName))
            .mapObject(IndexUsersHttpresponse.self)
            .map({ indexUsersHttpresponse -> UserInfo in
                self.user_cid = (indexUsersHttpresponse.data?.first)!.cid
                self.user_uid = (indexUsersHttpresponse.data?.first)!.uid
                return (indexUsersHttpresponse.data?.first)!
            })
            .flatMap({ UserInfo in
                userProvider.rx.request(.upLoad(UserInfo.cid!, UserInfo.uid!))
            })
            .subscribe{ event in
                switch event {
                case let .success(response):
                    let str = String(data: response.data, encoding: String.Encoding.utf8)
                    print("Success:", str ?? "")
                    self.Message = "解锁成功!"
                    break
                case let .error(error):
                    print("Error: \(error)")
                    self.Message = "Error: \(error)"
                    break
                }
            }.disposed(by: disposeBag)
    }

这是之前的代码。之前说过,在map中如果IndexUsersHttpresponse的data没有数据或者返回错误,那么会报错且不会跳转至subscribe的error中,导致程序崩溃。具体原因有待考证,但是却有方法可以避免此情况。

之前由于写法问题导致无法在flatMap中处理数据,学习之后发现原因是由于flatmap的函数其实是有返回值的,看一下他的定义:

public func flatMap<Result>(_ selector: @escaping (Self.Element) throws -> RxSwift.Single<Result>) -> RxSwift.Single<Result>

他返回了一个RxSwift.Single的类型,这个其实就是Rx封装好的一个返回类型,所以我只要写成这样就可以在flatMap中定义其他代码:

.flatMap{ indexUsersHttpresponse -> Single<Response> in
    if indexUsersHttpresponse.code == 10000 && indexUsersHttpresponse.data != nil {
        let userInfo = indexUsersHttpresponse.data?.first
        return userProvider.rx.request(.upLoad((userInfo?.cid)!, (userInfo?.uid)!))
    }
    else {

    }
}

这样会报错,因为else没有返回值。这里我希望在else的时候不做任何事情直接罢工,但是返回类型需要是Response,怎么办呢?我决定直接throw错误,throw的错误subscribe可以抓取到,然后dispose。那么我们需要自定义一个error:

struct XMLParsingError: Error {
    let message: String
}

这个error非常简单,只有一条用来记录信息的message,随后我们可以去掉map了,整体代码变成这样:

    func Deblocking(userName: String) {
        userProvider.rx.request(.getUserId(userName))
            .mapObject(IndexUsersHttpresponse.self)
            .flatMap{ indexUsersHttpresponse -> Single<Response> in
                if indexUsersHttpresponse.code == 10000 && indexUsersHttpresponse.data != nil {
                    let userInfo = indexUsersHttpresponse.data?.first
                    self.user_cid = userInfo?.cid
                    self.user_uid = userInfo?.uid
                    return userProvider.rx.request(.upLoad((userInfo?.cid)!, (userInfo?.uid)!))
                }
                else {
                    throw XMLParsingError(message: "Could not find userInfo")
                }
            }
            .subscribe{ event in
                switch event {
                case let .success(response):
                    let str = String(data: response.data, encoding: String.Encoding.utf8)
                    print("Success:", str ?? "")
                    self.Message = "解锁成功!"
                    break
                case let .error(error):
                    print("Error: \(error)")
                    self.Message = "Error: \( error)"
                    break
                }
            }.disposed(by: disposeBag)
    }

在flatmao中判断,如果不正确将抛出错误并且释放。

soapgu commented 3 years ago

很好,throw XMLParsingError(message: "Could not find userInfo")能不能写成类似Single.Error( exception )这种?,另外,你所有的代码块需要加上``swift,这样显示更美观一点

struct XMLParsingError: Error {
    let message: String
}
func Deblocking(userName: String) {
        userProvider.rx.request(.getUserId(userName))
            .mapObject(IndexUsersHttpresponse.self)
            .flatMap{ indexUsersHttpresponse -> Single<Response> in
                if indexUsersHttpresponse.code == 10000 && indexUsersHttpresponse.data != nil {
                    let userInfo = indexUsersHttpresponse.data?.first
                    self.user_cid = userInfo?.cid
                    self.user_uid = userInfo?.uid
                    return userProvider.rx.request(.upLoad((userInfo?.cid)!, (userInfo?.uid)!))
                }
                else {
                    throw XMLParsingError(message: "Could not find userInfo")
                }
            }
            .subscribe{ event in
                switch event {
                case let .success(response):
                    let str = String(data: response.data, encoding: String.Encoding.utf8)
                    print("Success:", str ?? "")
                    self.Message = "解锁成功!"
                    break
                case let .error(error):
                    print("Error: \(error)")
                    self.Message = "Error: \( error)"
                    break
                }
            }.disposed(by: disposeBag)
    }