Limiting concurrent access to a service class with RxSwift

南楼画角 提交于 2019-12-04 05:12:09

问题


Given a service class like this:

class Service {
    let networkService = NetworkService()

    func handleJobA(input: String) -> Observable<ResultA> {
        return networkService
            .computeA(input)
            .map { $0.a }
    }
}

And when I use it from the caller side like this:

let service = Service()

Observable
    .from(["Hello", "World"])
    .flatMap {
        service.handleJobA($0)
    }
    .subscribe()

Then this would send multiple requests to service at the same time. I wanted for the stream to wait until each request is done. That was achievable using the merge operator.

Observable
    .from(["Hello", "World"])
    .flatMap {
        Observable.just(
            service.handleJobA($0)
        )
    }
    .merge(maxConcurrent: 1)
    .subscribe()

So far, so good - the service will not perform multiple handleJobA tasks at the same time.

However, the concurrency is a service detail and the caller should NOT care about it. In fact, the service, at a later stage, might decide to allow for difference concurrency values.

Secondly, when I add a new method handleJobB, it must not be active at the same time as job A, and vice versa.

So my question is:

  1. How can I restrict the maxConcurrency to the handleJobA observable as a implementation detail?
  2. Which RxSwift pattern would allow to restrict this for any service method?

回答1:


You need a serial Scheduler that is dedicated to that service. Here is an example that can be pasted to a playground:

/// playground

import RxSwift

class Service {

    func handleJobA(input: String) -> Observable<String> {

        return Observable.create { observer in
            print("start job a")
            sleep(3)
            observer.onNext(input)
            print("complete job a")
            observer.onCompleted()
            return Disposables.create()
        }.subscribeOn(scheduler)
    }

    func handleJobB(input: String) -> Observable<String> {
        return Observable.create { observer in
            print("start job b")
            sleep(3)
            observer.onNext(input)
            print("complete job b")
            observer.onCompleted()
            return Disposables.create()
            return Disposables.create()
        }.subscribeOn(scheduler)
    }

    let scheduler = SerialDispatchQueueScheduler(internalSerialQueueName: "Service")
}


let service = Service()

_ = Observable.from(["hello","world","swift"])
    .flatMap { service.handleJobA(input: $0) }
    .subscribe(onNext:{
        print("result " + $0)
    })

_ = Observable.from(["hello","world","swift"])
    .flatMap { service.handleJobB(input: $0) }
    .subscribe(onNext:{
        print("result " + $0)
    })

import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true



回答2:


maybe you want concat operator,i wrote some test codes below see if this you want :

 func sleepAndPrint(label:String) -> Observable<String> {


        return Observable.create { obser -> Disposable in
            DispatchQueue.global().async {
                sleep(3)
                print("\(label) come")
                obser.onNext(label)
                obser.onCompleted()
            }

            return Disposables.create()
        }
    }


Observable.from(["hello","world","swift"])
    // we need observable of observable sequences so just use map
    // Observable<Observable<String>> in this case
    .map{
        sleepAndPrint(label: $0)
    }
    // Concatenates all inner observable sequences, as long as the previous observable sequence terminated successfully.
    .concat()

    .subscribe(onNext:{
        print("subscribe: " + $0)
    })
    .addDisposableTo(disposeBag)

    prints : 
      hello come
      subscribe: hello
      world come
      subscribe: world
      swift come
      subscribe: swift


来源:https://stackoverflow.com/questions/43794392/limiting-concurrent-access-to-a-service-class-with-rxswift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!