Home > Enterprise >  How to implement Promise.all like functionality in kotlin
How to implement Promise.all like functionality in kotlin

Time:01-25

Am trying to get messages from twillio server using its sdk method so on calling the method it return callback to return the List of messages. I have list of conversation,i want to get all messages for conversation so am using forEach like this

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

So i want to wait until all listners get executed and then want to change the state of ui.

CodePudding user response:

You can make all requests in parallel and wait for all of them to finish following next steps:

  1. Create a suspend function getMessage, which will be responsible for suspending the calling coroutine until request is executed. You can use suspendCoroutine or suspendCancellableCoroutine for that:

    suspend fun getMessage(conversation: Conversation) = suspendCoroutine<Message?> { continuation ->
        conversation.getMessageByIndex(conversation.lastMessageIndex, object : CallbackListener<Message> {
            override fun one rror(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. Run requests in parallel using async coroutine builder and Dispatchers.IO dispatcher to offload work from the Main Thread:

    async(Dispatchers.IO) {
        getMessage(conversation)
    }
    
  3. To run all this you need to use some instance of CoroutineScope to launch a coroutine. In ViewModel it can be viewModelScope, in Activity/Fragment - lifecycleScope. For example in 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
    }
    
  •  Tags:  
  • Related