0

I have a list of items which i need to extract some values and make an api call for each of the item. To do that, i'm using something like this_

Observable.from(myList)
   .flatMap{ item ->
      return serviceInteractor.uploadToServer(item)
   }
   .map { serverResponse ->
       return serverResponse.getResponseCode
   }
   .toList()
   .subscrible{ responseList ->
   // do something with all the responses
   }

Ok so the problem is, i don't know why all the calls are made in parallel. Isn't it supposed to wait for the first response, map the results, proceed to the next item from the Observable.from() and at the end return the final list of responseMessages? What is happening is, everything happens at the same time. To confirm this, if i put a delay(1, TimeUnit.Seconds) before the toList method, everything happens at the same time, only the final onNext is delayed.

How can i accomplish this? Have a list of ids, want to upload to server one by one, waiting for each one to complete, proceed to next if success or fail

johnny_crq
  • 4,291
  • 5
  • 39
  • 64
  • no, it is not supposed to do that. – njzk2 Aug 17 '16 at 13:39
  • this answer describe an operator to do what you ask: http://stackoverflow.com/a/33633753/671543 – njzk2 Aug 17 '16 at 13:41
  • Shouldn't the first flatMap be a simple map operator since the Observable.from(list) returns an Observable already? I'm not experienced with RxJava though – GSala Aug 17 '16 at 14:25

2 Answers2

1

flatMap will "stack" calls. It will subscribe to each of Observable then emit results in order of their arrival. So results may not be ordered (cf documentation).

If you wants that results are ordered, you should look at the concatMap operator.(see documentation)

Observable.from(myList)
     .concatMap{ item ->
              return serviceInteractor.uploadToServer(item)
      }
     .map { serverResponse ->
         return serverResponse.getResponseCode
      }
     .toList()
     .subscrible{ responseList ->
         // do something with all the responses
     }

You can get more information throught this blog post.

dwursteisen
  • 11,435
  • 2
  • 39
  • 36
0

Yes you need to use ConcatMap

Flat map uses merge operator while concatMap uses concat opertor.

so sequence will be like this

flatMap output sequence is merged
concatMap output sequence is ordered

as described in this answer

here you can take a look on this example

String arrData[] = {"0", "1", "2", "3", "4"};
Integer arrDelay[] = {1000, 6000, 4000, 9000, 2000};

Observable.from(arrData)
            .concatMap(s -> Observable.from(arrData)
                      .delay(arrDelay[Integer.parseInt(s)],TimeUnit.MILLISECONDS))

            .map(integer -> integer)
            .toList()
            .doOnCompleted(() -> Log.v("log", "doOnCompleted"))
            .subscribe(integer -> Log.v("log", "" + integer));

here you can check that delay will be total of arrDelay item as we have used toList()

i know i am late to give answer on this :)

Community
  • 1
  • 1
Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75