首页 > 解决方案 > 如何在 RxSwift 中按顺序和非并行循环遍历数组?

问题描述

我有一个需要发送到服务器的对象列表,我想一个接一个地执行此操作(而不是并行执行)。在发送完所有对象并且没有错误之后,我想运行其他可做不同事情的 Observables。

let objects = [1, 2, 3]

let _ = Observable.from(objects).flatMap { object -> Observable<Void> in
    return Observable.create { observer in
        print("Starting request \(object)")
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // one request takes ~2sec
            print("Request \(object) finished")
            observer.onNext(Void())
            observer.onCompleted()
        }
        return Disposables.create()
    }
}.flatMap { result -> Observable<Void> in
    print("Do something else (but only once)")
    return Observable.just(Void())
}.subscribe(
    onNext: {
        print("Next")
    },
    onCompleted: {
        print("Done")
    }
)

我得到的是

Starting request 1
Starting request 2
Starting request 3
Request 1 finished
Do something else (but only once)
Next
Request 2 finished
Do something else (but only once)
Next
Request 3 finished
Do something else (but only once)
Next
Done

整个过程在 2 秒后结束。我想要的是

Starting request 1
Request 1 finished
Starting request 2
Request 2 finished
Starting request 3
Request 3 finished
Do something else (but only once)
Next
Done

整个序列应在 6 秒后结束(因为它不是并行执行的)。

我让它与递归函数一起工作。但是有很多请求,这以我想避免的深度递归堆栈结束。

标签: rx-swift

解决方案


使用concatMap而不是flatMap为了一次发送一个而不是一次发送所有。在此处了解更多信息:

RxSwift 的 FlatMap 多面

然后只做一次之后,使用toArray(). 这是一个完整的例子:

let objects = [1, 2, 3]

_ = Observable.from(objects)
    .concatMap { object -> Observable<Void> in
        return Observable.just(())
            .debug("Starting Request \(object)")
            .delay(.seconds(2), scheduler: MainScheduler.instance)
            .debug("Request \(object) finished")
    }
    .toArray()
    .flatMap { results -> Single<Void> in
        print("Do something else (but only once)")
        return Single.just(())
    }
    .subscribe(
        onSuccess: { print("done") },
        onError: { print("error", $0) }
    )

推荐阅读