如何在 kotlin 中实现类似 Promise.all 的功能

How to implement Promise.all like functionality in kotlin

我正在尝试使用其 sdk 方法从 twillio 服务器获取消息,因此调用它 return 回调到 return 消息列表的方法。我有对话列表,我想获取所有对话消息,所以我像这样使用 forEach

  allConversations.forEach { conversation ->
            conversation.getMessageByIndex(conversation.lastMessageIndex){
                conversationLastMessages[conversation.sid] = it
            }
        }

所以我想等到所有的监听器都被执行,然后想改变 ui 的状态。

您可以并行发出所有请求并等待所有请求完成以下后续步骤:

  1. 创建一个suspend函数getMessage,它将负责挂起调用协程直到请求被执行。您可以为此使用 suspendCoroutinesuspendCancellableCoroutine

    suspend fun getMessage(conversation: Conversation) = suspendCoroutine<Message?> { continuation ->
        conversation.getMessageByIndex(conversation.lastMessageIndex, object : CallbackListener<Message> {
            override fun onError(errorInfo: ErrorInfo) {
                continuation.resume(null) // resume calling coroutine
                // or continuation.resumeWithException() depend whether you want to handle Exception or not
            }
    
            override fun onSuccess(result: Message) {
                continuation.resume(result) // resume calling coroutine
            }
        })
    }
    
  2. 运行 使用 async 协程构建器和 Dispatchers.IO 调度器并行请求从主线程卸载工作:

    async(Dispatchers.IO) {
        getMessage(conversation)
    }
    
  3. 为了 运行 所有这些你需要使用 CoroutineScope 的一些实例来启动协程。在 ViewModel 中可以是 viewModelScope,在 Activity/Fragment - lifecycleScope 中。例如 ViewModel:

    viewModelScope.launch {
        val allConversations = ...
    
        allConversations.map { conversation ->
            async(Dispatchers.IO) {
                getMessage(conversation)
            }
        }.awaitAll() // waiting for all request to finish executing in parallel
         .forEach { message ->   // iterate over List<Message> and fill conversationLastMessages
             conversationLastMessages[message.getConversationSid()] = message
         }
    
         // here all requests are completed and UI can be updated
    }