如何处理在使用RxSwift的Observable zip时处理多个API调用的成功和失败情况。

huangapple go评论48阅读模式
英文:

How to handle success case and failure case for multiple API calls when using Observable zip in RxSwift

问题

我使用Observable.zip()调用了两个独立的API。在这种情况下,如果第一个API失败(返回某种错误),即使第二个API成功,也不会在subscribe(onNext)闭包内执行,反之亦然。我仍希望从每个API调用中获取成功和失败的情况。<br>如何使用Observable zip解决这个问题,或者我应该使用其他方法来实现这一点?

Observable.zip(api1(), api2())
    .subscribe { [weak self] in
        print($1) // 如果第一个API调用失败,这里不会打印任何内容。
    }
    .onError: {
        print("error", $0)
    }
    .disponseBag(by: disposebag)
英文:

I call two independent API calls using Obeservable.zip(). In this case, if the first API fails(returning some kind of error), the second API never executes inside the subscribe(onNext) closure even if it is successful. and vice versa. I still want the success case and failure case from each api call. <br> How can I solve this issue using Observable zip or should I use another method to achieve this?

Observable.zip(api1(), api2())
.subscribe { [weak self] in
 print($1) //if the first api call fails, Nothing prints out here.
}
.onError: {
 print(&quot;error&quot;, $0)
}
.disponseBag(by: disposebag)

答案1

得分: 0

不只是第一个失败的情况。如果任何一个 Observable 失败,另一个将被处理,你的 onNext 将不会被调用。

有几种不同的方法可以解决这个问题,它们都涉及将 error 事件转换为 next 事件。

你可以使用:

Observable.zip(api1.materialize(), api2.materialize())
    .subscribe(
        onNext: { lhs, rhs in
            switch (lhs, rhs) {
            case let (.next(left), .next(right)):
                print(left, right)
            case let (.error(left), .next(right)):
                print(left, right)
            case let (.next(left), .error(right)):
                print(left, right)
            case let (.error(left), .error(right)):
                print(left, right)
            default:
                return
            }
    },
    onError: { _ in /*不会被调用*/ })

或者如果你不关心错误,你可以将它们转换为 Optionals:

Observable.zip(
    api1.map(Optional.some).catch { _ in .just(nil) },
    api2.map(Optional.some).catch { _ in .just(nil) }
)
    .subscribe(
        onNext: { lhs, rhs in
            print(lhs as Any, rhs as Any) // 错误将为 `nil`
        },
    onError: { _ in /*不会被调用*/ })

如果你不需要两个网络调用的结果来进行工作,那么另一个选择是保持两个请求分开:

api1
    .subscribe(onNext: { print($0) }, onError: { print($0) })
api2
    .subscribe(onNext: { print($0) }, onError: { print($0) })
英文:

It's not just if the first fails. If either Observable fails, the other will be disposed and your onNext will not be called.

There are a few different ways to solve this, and they all involve turning the error event into a next event.

You could use:

Observable.zip(api1.materialize(), api2.materialize())
	.subscribe(
		onNext: { lhs, rhs in
			switch (lhs, rhs) {
			case let (.next(left), .next(right)):
				print(left, right)
			case let (.error(left), .next(right)):
				print(left, right)
			case let (.next(left), .error(right)):
				print(left, right)
			case let (.error(left), .error(right)):
				print(left, right)
			default:
				return
			}
	},
	onError: { _ in /*will not get called*/ })

or you if you don't care about the errors, you could convert them to Optionals:

Observable.zip(
	api1.map(Optional.some).catch { _ in .just(nil) },
	api2.map(Optional.some).catch { _ in .just(nil) }
)
	.subscribe(
		onNext: { lhs, rhs in
			print(lhs as Any, rhs as Any) // errors will be `nil`
		},
	onError: { _ in /*will not get called*/ })

If you don't need the results of both network calls to do work, then another option would be to just keep the two requests separate:

api1
    .subscribe(onNext: { print($0) }, onError: { print($0) })
api2
    .subscribe(onNext: { print($0) }, onError: { print($0) })

huangapple
  • 本文由 发表于 2023年3月4日 08:58:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75633024.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定