2016-05-27 18 views
4

タップしたログインボタンでログインタスクを開始したいと思います。この作業が完了した後、ユーザーの注文リスト、配送先住所、希望のリスト、その他の情報を取得します。 startTaskはボタンです。ユーザーがタップしますが、私はこれらのタスクを開始しますが、ログインタスクが失敗した場合、ユーザーはstartTaskボタンをもう一度タップします。
サンプルコードRxSwift非同期タスク

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 } 

    startTask 
     .rx_tap 
     .flatMapLatest{ result } 
     .catchError{ error in 
      .....error...... 
      return Observable.empty() 
     } 
     .subscribeNext{ tasks in 
      .....all completed.... 
     } 
     .addDisposableTo(disposeBag) 
} 

private func login()-> Observable<String> { 
    return Observable.create{ observer in 
     performClosure(afterDealy: 1, onMainQueue: false) { 
      if arc4random() % 4 == 0 { 
       observer.onNext("login finished") 
       observer.onCompleted() 
      } else { 
       observer.onError(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "some error"])) 
      } 
     } 
     return AnonymousDisposable{} 
    } 
} 

private func asyncTask(name: String)-> Observable<String> { 
    return Observable.create{ observer in 
     let delay = Double(arc4random() % 6 + 1) 
     performClosure(afterDealy: delay, onMainQueue: false) { 
      observer.onNext(name) 
      observer.onCompleted() 
     } 
     return AnonymousDisposable{} 
    } 
} 

func performClosure(afterDealy delay: Double, onMainQueue mainQueueOrNot: Bool, action: dispatch_block_t) { 
    let delayIntervals = Double(NSEC_PER_SEC) * delay 
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delayIntervals)) 
    let queue = mainQueueOrNot ? dispatch_get_main_queue() : dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) 
    dispatch_after(time, queue, action) 
} 

答えて

3

エラーが発生すると、ストリームが終了します。これをボタンのレベルで発生させたくないので、より深いレベルでエラーを捕捉する必要があります。

例:あなたはflatMapを通じてバブルアップから実際の受信エラーを防ぐことができます

startTask 
    .rx_tap 
    .flatMapLatest{ 
     result 
      .catchError{ error in 
       .....error...... 
       return Observable.empty() 
      } 
    } 
    .subscribeNext{ tasks in 
     .....all completed.... 
    } 
    .addDisposableTo(disposeBag) 

この方法です。

エラーが発生した場合は、何らかの結果の列挙型(推奨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) 
+0

、ストリームが終了します。ありがとう、それは非常に便利です!関連するRxSwiftの慣行(ドキュメンテーションを除く)を見つけることができるソース/例があるかどうか尋ねてもよろしいですか? –

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ハンドラを移動し、いくつかの種類を返すことです。ここでは

は何が起こっているかのサンプル出力です subscribeNextのエラーを処理する列挙型は Resultです。

は、ここで私は

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) 
} 

を説明してきた技術を使用して、調整test()機能だと出力は次のとおりです。あなたは、メインのシーケンスを見ることができるように

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

Here'reあなたが役に立つかもしれないリソースの一部:

  1. https://github.com/ReactiveX/RxSwift/tree/master/RxExample
  2. http://rx-marin.com/
  3. https://github.com/artsy/eidolon
  4. https://realm.io/news/ - 彼らはRxSwiftにいくつかの交渉を持っています
  5. https://gist.github.com/JaviLorbada/4a7bd6129275ebefd5a6 - FRPリソースのリスト
  6. http://slack.rxswift.org/ - エラーが発生すると全能RxSwiftコミュニティメンバー:)
+0

ありがとう、それは非常に便利です!関連するRxSwiftの慣行(ドキュメンテーションを除く)を見つけることができるソース/例があるかどうか尋ねてもよろしいですか? –

+0

役に立つかもしれないリソースの短いリストについては、私のアップデートをご覧ください – NikGreen