我希望通过点击登录按钮启动登录任务,完成后,获取用户订单列表,送货地址,愿望清单,其他信息。
startTask是一个按钮,用户点击它,我将启动这些任务,但是现在如果登录任务失败,用户再次点击startTask按钮,我就无法再次启动这些任务,为什么?
示例代码
<div id="nav">
<a href="istHome.html"><img src="Home.PNG" height="50"></a>
<a href="Operations.html"><img src="Operations and Maintenence.PNG" height="50"></a>
<a href="System.html"><img src="Systems Development.PNG" height="50"></a>
<a href="EndUser.html"><img src="EndUserSupport.PNG" height="50"></a>
<a href="AboutMe.html"><img src="About Me.PNG" height="50"></a>
</div>
答案 0 :(得分:3)
发生错误后,流终止。您不希望在按钮级别发生这种情况,因此您必须在更深层次上捕获错误。
例如:
startTask
.rx_tap
.flatMapLatest{
result
.catchError{ error in
.....error......
return Observable.empty()
}
}
.subscribeNext{ tasks in
.....all completed....
}
.addDisposableTo(disposeBag)
这样可以防止实际的Rx错误冒泡到flatMap。
如果您需要在出错时执行某些操作,您可能希望将结果包装在某种结果枚举中(建议使用https://github.com/antitypical/Result)。
这方面的一个例子是:
startTask
.rx_tap
.flatMapLatest{
result
.map { Result.Success(result: $0)
.catchError{ error in return Result.Error(error: $0) }
}
.subscribeNext{ result in
switch(result) {
case .Success(let result):
//display happy case
case .Error(let error):
//display sad case
}
.addDisposableTo(disposeBag)
答案 1 :(得分:2)
如catchError
文件中所述:
返回一个包含源序列元素的可观察序列,后跟由处理程序产生的可观察序列产生的元素,以防发生错误。
因此,当您的登录链中发生错误时,错误会在catchError
闭包中被捕获,并且序列将被终止。
以下是正在发生的事情的示例输出:
2016-05-27 10:03:18.634: AppDelegate.swift:59 (test()) -> subscribed
2016-05-27 10:03:19.792: AppDelegate.swift:59 (test()) -> Event Error(Error Domain= ...ription=some error})
2016-05-27 10:03:19.796: AppDelegate.swift:59 (test()) -> disposed
在类似情况下对我有用的是将catchError
处理程序移动到闭包内部,这实际上做了一些工作(例如执行网络请求)并返回某种Result
枚举来处理错误在subscribeNext
。
这是使用我所描述的技术的调整后的test()
函数
enum Result<T>
{
case Success(value: T)
case Failure(error: ErrorType)
}
private func test() {
let data = ["fetch order list", "fetch shipping addresses", "fetch wishlist", "fetch other info"]
let fetchInfoTasks = data.map{ asyncTask($0) }.toObservable()
let someTasks = fetchInfoTasks.merge().toArray()
let result = login().flatMapLatest{ _ in someTasks }
let resultHandled = result.map{ Result.Success(value: $0) }
.catchError { .just(Result.Failure(error: $0)) }
let startTask = Observable<Int>.timer(0, period: 5, scheduler: MainScheduler.instance);
startTask
.flatMapLatest{ _ in resultHandled }
.debug()
.subscribeNext{ (result) in
print("\(result)")
}
.addDisposableTo(disposeBag)
}
输出是:
2016-05-27 10:07:25.507: AppDelegate.swift:59 (test()) -> subscribed
2016-05-27 10:07:26.614: AppDelegate.swift:59 (test()) -> Event Next(Failure(Error D...iption=some error}))
Failure(Error Domain= Code=-1 "some error" UserInfo={NSLocalizedDescription=some error})
2016-05-27 10:07:34.878: AppDelegate.swift:59 (test()) -> Event Next(Success(["fetch...ipping addresses"]))
Success(["fetch wishlist", "fetch order list", "fetch other info", "fetch shipping addresses"])
2016-05-27 10:07:41.603: AppDelegate.swift:59 (test()) -> Event Next(Failure(Error D...iption=some error}))
Failure(Error Domain= Code=-1 "some error" UserInfo={NSLocalizedDescription=some error})
2016-05-27 10:07:46.588: AppDelegate.swift:59 (test()) -> Event Next(Failure(Error D...iption=some error}))
Failure(Error Domain= Code=-1 "some error" UserInfo={NSLocalizedDescription=some error})
正如您所看到的,主要序列(在我的情况下是它的计时器,在您的按钮点击事件序列中)不会出错,您可以在subscribeNext
处理结果。希望有所帮助!
<强> UPD 强>
以下是您可能会发现有用的一些资源: