如何使用物化处理永无止境的链上的错误?

How to handle Errors on never ending chain with materialize?

想象一下用户想要保存某种列表的以下链:

var saveChain = userTappedSaveListSubject
        .doOnNext { list -> Void in // create pdf version
            let pdfFactory = ArticleListPDFFactory()
            list.pdf = try pdfFactory.buildPDF(list)
            try database.save(list)
        }
        .flatMap { list in
              AuthorizedNetworking.shared.request(.createList(try ListRequestModel(list)))
                    .filter(statusCode: 201)
                    .map { _ in list }
        }
        .doOnNext { list in
            list.uploaded = true
            try database.save(list)
            try Printer().print(list)
    }
    .materialize()
    .share()

链中的每个运算符都可能发生错误,这将终止流并且用户将无法重试保存和打印列表(整个链被处理掉)。

最后,通过将可观察对象绑定到文本字段,用户应该看到 "success" 或 "failure" 屏幕:

Observable.of(
        saveChain.elements().map { _ in
            ("List saved!", subtitle: "Saving successfull")
        }, 
        saveChain.errors().map { error in
            ("Error!", subtitle: error.localizedDescription)
        })
        .merge()

错误应该如何处理?

这是显而易见的解决方法:

let saveChain = userTappedSaveListSubject
    .flatMap { list in
        Observable.just(list)
            .do(onNext: { list -> Void in // create pdf version
                let pdfFactory = ArticleListPDFFactory()
                list.pdf = try pdfFactory.buildPDF(list)
                try database.save(list)
            })
            .flatMap { list in
                AuthorizedNetworking.shared.request(.createList(try ListRequestModel(list)))
                    .filter(statusCode: 201)
                    .map { _ in list }
            }
            .do(onNext: { list in
                list.uploaded = true
                try database.save(list)
                try Printer().print(list)
            })
            .materialize()
    }
    .share()

但是,由于混合范例,此代码存在许多问题。

  • 您正在 Observable 中传递一个可变的 class。这是有问题的,因为它是一个功能范例,所以系统期望包含的类型是 struct/enum 或不可变的 class.
  • 你依赖副作用来再次加载所述可变 class 对象是很奇怪的,并且违反了范例。