使用 Result 防止网络请求错误中止事件序列

This commit is contained in:
Fin 2020-11-18 16:34:17 +08:00
parent abe4c4e419
commit 585c8670df
4 changed files with 118 additions and 81 deletions

View File

@ -59,17 +59,25 @@ class Client: NSObject {
func bindDeviceToken(){
if let token = Settings[.deviceToken] , token.count > 0{
_ = BarkApi.provider.request(.register(key: key, devicetoken: token)).filterResponseError().subscribe(onNext: { (json) in
if let key = json["data","key"].rawString() {
Client.shared.key = key
self.state = .ok
}
else{
self.state = .serverError
}
}, onError: { (error) in
self.state = .serverError
})
BarkApi.provider
.request(.register(
key: key,
devicetoken: token))
.filterResponseError()
.subscribe(onNext: { (json) in
switch json {
case .success(let json):
if let key = json["data","key"].rawString() {
Client.shared.key = key
self.state = .ok
}
else{
self.state = .serverError
}
case .failure:
self.state = .serverError
}
}).disposed(by: rx.disposeBag)
}
}

View File

@ -35,37 +35,48 @@ extension Swift.Error {
extension Observable where Element: Moya.Response {
/// HTTP
func filterHttpError() -> Observable<Element> {
return filter{ response in
if (200...209) ~= response.statusCode {
return true
func filterHttpError() -> Observable<Result<Element,ApiError>> {
return
catchErrorJustReturn(Element(statusCode: 599, data: Data()))
.map { (response) -> Result<Element,ApiError> in
if (200...209) ~= response.statusCode {
return .success(response)
}
else{
return .failure(ApiError.Error(info: "网络错误"))
}
}
print("网络错误")
throw ApiError.Error(info: "网络错误")
}
}
/// CODE
func filterResponseError() -> Observable<JSON> {
return filterHttpError().map({ (response) -> JSON in
let json = try JSON(data: response.data)
var code = 400
var msg:String?
if let codeStr = json["code"].rawString(), let c = Int(codeStr) {
code = c
func filterResponseError() -> Observable<Result<JSON,ApiError>> {
return filterHttpError()
.map{ response -> Result<JSON,ApiError> in
switch response {
case .success(let element):
do {
let json = try JSON(data: element.data)
if let codeStr = json["code"].rawString(),
let code = Int(codeStr),
code == 200{
return .success(json)
}
else{
var msg:String = ""
if json["message"].exists() {
msg = json["message"].rawString()!
}
return .failure(ApiError.Error(info: msg))
}
}
catch {
return .failure(ApiError.Error(info: error.rawString()))
}
case .failure(let error) :
return .failure(ApiError.Error(info: error.rawString()))
}
}
if json["message"].exists() {
msg = json["message"].rawString()!
}
if (code == 200){
return json
}
switch code {
default: throw ApiError.Error(info: msg ?? "未知错误")
}
})
}
/// Response JSON Model
@ -73,43 +84,54 @@ extension Observable where Element: Moya.Response {
/// - Parameters:
/// - typeName: Model Class
/// - dataPath: ["data","links"]
func mapResponseToObj<T: Mappable>(_ typeName: T.Type , dataPath:[String] = ["data"] ) -> Observable<T> {
func mapResponseToObj<T: Mappable>(_ typeName: T.Type , dataPath:[String] = ["data"] ) -> Observable<Result<T,ApiError>> {
return filterResponseError().map{ json in
var rootJson = json
if dataPath.count > 0{
rootJson = rootJson[dataPath]
}
if let model: T = self.resultFromJSON(json: rootJson) {
return model
}
else{
throw ApiError.Error(info: "json 转换失败")
switch json {
case .success(let json):
var rootJson = json
if dataPath.count > 0{
rootJson = rootJson[dataPath]
}
if let model: T = self.resultFromJSON(json: rootJson) {
return .success(model)
}
else{
return .failure(ApiError.Error(info: "json 转换失败"))
}
case .failure(let error):
return .failure(error)
}
}
}
/// Response JSON Model Array
func mapResponseToObjArray<T: Mappable>(_ type: T.Type, dataPath:[String] = ["data"] ) -> Observable<[T]> {
func mapResponseToObjArray<T: Mappable>(_ type: T.Type, dataPath:[String] = ["data"] ) -> Observable<Result<[T],ApiError>> {
return filterResponseError().map{ json in
var rootJson = json;
if dataPath.count > 0{
rootJson = rootJson[dataPath]
}
var result = [T]()
guard let jsonArray = rootJson.array else{
return result
switch json {
case .success(let json):
var rootJson = json;
if dataPath.count > 0{
rootJson = rootJson[dataPath]
}
var result = [T]()
guard let jsonArray = rootJson.array else{
return .failure(ApiError.Error(info: "Root Json 不是 Array"))
}
for json in jsonArray{
if let jsonModel: T = self.resultFromJSON(json: json) {
result.append(jsonModel)
}
else{
return .failure(ApiError.Error(info: "json 转换失败"))
}
}
return .success(result)
case .failure(let error):
return .failure(error)
}
for json in jsonArray{
if let jsonModel: T = self.resultFromJSON(json: json) {
result.append(jsonModel)
}
else{
throw ApiError.Error(info: "json 转换失败")
}
}
return result
}
}

View File

@ -70,15 +70,18 @@ class HomeViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
_ = BarkApi.provider.request(.ping(baseURL: ServerManager.shared.currentAddress))
BarkApi.provider
.request(.ping(baseURL: ServerManager.shared.currentAddress))
.filterResponseError()
.subscribe(
onNext: { _ in
Client.shared.state = .ok
},
onError: { _ in
Client.shared.state = .serverError
})
onNext: { response in
switch response {
case .success:
Client.shared.state = .ok
case .failure:
Client.shared.state = .serverError
}
}).disposed(by: rx.disposeBag)
}
override func viewDidLoad() {

View File

@ -64,17 +64,21 @@ class NewServerViewController: UIViewController {
@objc func done(){
self.addressTextField.resignFirstResponder()
if let text = addressTextField.text, let _ = URL(string: text) {
_ = BarkApi.provider.request(.ping(baseURL: text))
BarkApi.provider
.request(.ping(baseURL: text))
.filterResponseError()
.subscribe(onNext: {[weak self] (_) in
self?.navigationController?.popViewController(animated: true)
ServerManager.shared.currentAddress = text
self?.showSnackbar(text: NSLocalizedString("AddedSuccessfully"))
Client.shared.bindDeviceToken()
.subscribe(onNext: {[weak self] (response) in
switch response {
case .success:
self?.navigationController?.popViewController(animated: true)
ServerManager.shared.currentAddress = text
self?.showSnackbar(text: NSLocalizedString("AddedSuccessfully"))
Client.shared.bindDeviceToken()
case .failure(let error):
self?.showSnackbar(text: "\(NSLocalizedString("InvalidServer"))\(error.rawString())")
}
}, onError: {[weak self] (error) in
self?.showSnackbar(text: "\(NSLocalizedString("InvalidServer"))\(error.localizedDescription)")
})
}).disposed(by: rx.disposeBag)
}
else{
self.showSnackbar(text: NSLocalizedString("InvalidURL"))