1

I need to create dependent API calls where the second one needs a value returned by the first one. First thing that comes to mind is using flatMap

ApiManager.shared
    .createReport(report: report)
    .flatMap { (report) -> Observable<Report> in
        return ApiManager.shared.createReportStep(reportID: report.ID)
    }

createReport returns Observable<Report> where after successfull call returns updated Report model(with ID), after that I need to call API to create report step, where report.ID is needed.

Everything looks and works fine with that code, but the problem comes when I need to do something after each of these steps(createReport and createReportStep). I placed code in onNext block, but it is called only once, after both of the steps are completed.

Is there a way to receive onNext signal after both steps? I could use something like this:

ApiManager.shared
      .createReport(report: report)
      .concat(ApiManager.shared.createReportStep(reportID: report.ID))

Which would emmit two signals like I want, but then again where do I get updated report.ID from to pass to createReportStep?

  • Please help me understand your problem better. After creating a `Report`, you wish to create a `ReportStep` which requires the report ID generated after creating a report. The next thing you want to do is to have access to both the `Report` and the `ReportStep` objects that were just created. Is that correct? – dsapalo Nov 11 '16 at 06:34

1 Answers1

2

If you don't mind the time component and only need to have access to both report and what is returned by createReportStep(reportID:), you could go with creating a tuple in flatMap's block

ApiManager.shared
    .createReport(report: report)
    .flatMap { (report) -> Observable<Report> in
        return ApiManager.shared.createReportStep(reportID: report.ID)
            .map { (report, $0) }
    }

The resulting observable would contain both results in a tuple.


If the time component is important, you could do the following

let report = ApiManager.shared
  .createReport(report: report)
  .share()

let reportStep = report.map { $0.ID }.flatMap(ApiManager.shared.createReportStep)

Observable.concat([report, reportStep])

Here, the important bit is the share call. It will ensure createReport performs its work only once, but you would have two next events as requested.

tomahh
  • 13,441
  • 3
  • 49
  • 70
  • I would guess that the time component is indeed important, assuming that Report IDs are unknown until the models are successfully created on the database. But that is merely a guess. :) lazyNeighbour would know his use case better than me. – dsapalo Nov 15 '16 at 15:51