Kotlin сопрограммы, как асинхронизировать список вызовов и вернуть результат в виде карты

var responseMap = mutableMapOf<VendorType, ChargeResponse>()
  requests.forEach {
    val response = when (it.vendorType) {
        VendorType.Type1 -> service.chargeForType1()
        VendorType.Type2 -> service.chargeForType2()

      else -> {
        throw NotImplementedError("${it.vendorType} does not support yet")
      }
    }
    responseMap[it.vendorType] = response
  }
  responseMap

Поэтому я хочу, чтобы все функции service.charge выполнялись в отдельном потоке. Верните карту, когда все будет сделано


person Hejiujiu    schedule 18.08.2020    source источник
comment
Является ли service.charge длинным вычислением или это получение чего-то из сети?   -  person Tenfour04    schedule 18.08.2020
comment
он обращается к другому сервису, чтобы взимать с пользователей деньги. 2-3 секунды каждый   -  person Hejiujiu    schedule 18.08.2020
comment
Обычно такие функции либо являются функциями Kotlin suspend, либо принимают обратный вызов. Есть ли библиотека, с которой вы работаете?   -  person Tenfour04    schedule 18.08.2020
comment
Использовал @Async с completableFuture. Но до сих пор не знаю, как использовать CompletableFuture в этой ситуации.   -  person Hejiujiu    schedule 18.08.2020
comment
Вы используете библиотеку Java или почему у вас есть полное будущее? Если вы контролируете код, обеспечивающий будущее, а также его kotlin, может быть полезно вместо этого использовать сопрограммы kotlin.   -  person DownloadPizza    schedule 19.08.2020
comment
Сначала я использовал для этого lib. Но я перешел на сопрограммы   -  person Hejiujiu    schedule 19.08.2020


Ответы (1)


Надеюсь решить вашу проблему:

Предположим, ваш сервис и запрос следующим образом:

interface Service {
  suspend fun chargeForType1(): ChargeResponse
  suspend fun chargeForType2(): ChargeResponse
}

data class Request(val vendorType: VendorType)
suspend fun requestAll(requests: List<Request>): Map<VendorType, ChargeResponse> {
  return coroutineScope {
    requests
        .map { request ->
          async {
            request.vendorType to when (request.vendorType) {
              VendorType.Type1 -> service.chargeForType1()
              VendorType.Type2 -> service.chargeForType2()
              else -> throw NotImplementedError("${request.vendorType} does not support yet")
            }
          }
        }
        .awaitAll()
        .toMap()
  }
}
person Petrus Nguyễn Thái Học    schedule 18.08.2020
comment
Позвольте мне попробовать это - person Hejiujiu; 18.08.2020
comment
Спасибо, вроде работает. Однако requestAll вызывается другой функцией, и я получил Suspend function 'requestAll' should be called only from a coroutine or another suspend function - person Hejiujiu; 19.08.2020
comment
Вы можете использовать CoroutineScope.launch { ... }, чтобы вызвать его - person Petrus Nguyễn Thái Học; 19.08.2020