对集合中的每个项目的异步调用

时间:2017-08-31 06:55:53

标签: java kotlin rx-java rx-kotlin

我有一个问题,到目前为止我无法解决 我是RxKotlin的新手,所以这可能很容易。请看一下代码:

    override fun infos(): Stream<Info> =
        client.infoAboutItem(identifier)
                .map {
                    val itemId = it.itemId ?: ""
                    val item = client.itemForId(itemId)
                    ClientInfo(client, it, source, item) as Info
                }
                .let { AccessStream(it) }

stream是我们自制的系列。 Map是一种允许您迭代该集合中的每个项目的方法。

这里的问题是

 client.itemForId(itemId)

是一个http调用,它返回一个不理想的Single。

我想在map中创建一个异步调用,它将返回Item而不是Single,然后将其传递给ClientInfo。我到目前为止尝试过的事情是在地图中使用subscribe并使用blockingGet()方法,但即使我在不​​同的线程上观察和订阅,这也会阻止主线程

因此它涉及对集合中的每件事进行异步调用。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

您可以尝试返回Observable<Stream<Info>>,然后看起来像:

   override fun infos(): Observable<Stream<Info>> = 
                Observable.from(client.infoAboutItem(identifier))
                        .flatMapSingle {
                            val itemId = it.itemId ?: ""
                            client.itemForId(itemId)
                        }
                        .map { 
                            ClientInfo(client, it, source, item) as Info
                         }
                        .toList()
                        .flatMap {
                            AccessStream(it)
                        }

答案 1 :(得分:0)

您应该将这些昂贵的操作包装到observable中,并使用平面地图将这些数据压缩到客户端信息中。

我写了一个小样本来展示它。

class SimpleTest {
  val testScheduler = TestScheduler()

  @Test
  fun test() {
    infos().observeOn(Schedulers.immediate())
        .subscribe { logger("Output", it.toString()) }

    testScheduler.advanceTimeBy(10, TimeUnit.MINUTES)
  }

  fun infos(): Single<List<ClientInfo>> {
    return Observable.from(infoAboutItem("some_identifier"))
        .doOnNext { logger("Next", it.toString()) }
        .flatMap { aboutItem ->
          Observable.fromCallable { itemForId(aboutItem.itemId) }
              .subscribeOn(testScheduler)
              .map { ClientInfo(aboutItem = aboutItem, item = it) }
        }
        .doOnNext { logger("Next", it.toString()) }
        .toList()
        .toSingle()
  }

  data class ClientInfo(
      val id: String = UUID.randomUUID().toString(),
      val aboutItem: AboutItem,
      val item: Item
  )

  data class AboutItem(val itemId: String = UUID.randomUUID().toString())
  data class Item(val id: String = UUID.randomUUID().toString())

  fun infoAboutItem(identifier: String): List<AboutItem> {
    return (1..10).map { AboutItem() }
  }

  fun itemForId(itemId: String): Item {
    val sleepTime = Random().nextInt(1000).toLong()
    Thread.sleep(sleepTime)
    return Item()
  }

  fun logger(tag: String, message: String): Unit {
    val formattedDate = Date(Schedulers.immediate().now()).format()
    System.out.println("$tag @ $formattedDate: $message")
  }

  fun Date.format(): String {
    return SimpleDateFormat("HH:mm:ss.SSS", Locale.US).format(this)
  }
}