ZargorNET
02/11/2019, 3:28 PMkotlin
private val queue: Deque<() -> Unit> = LinkedList()
fun addJob(req: String, callback: (String) -> Unit) {
this.queue.offer {
callback(req)
}
}
//WILL RUN LATER AT AN UNSPECIFIED POINT OF TIME
fun pullJob() {
val func = this.queue.poll()
if (func != null)
func()
}
But I understood suspended functions in such way that they're there to get rid of the callbacks. So can I beautify this code with suspended functions? If so, how?marstran
02/11/2019, 3:35 PMZargorNET
02/11/2019, 3:35 PMmarstran
02/11/2019, 3:37 PMZargorNET
02/11/2019, 3:41 PMmarstran
02/11/2019, 3:41 PMmarstran
02/11/2019, 3:43 PMfun <T, R> CoroutineScope.rateLimiter(responseChannel: Channel<R>, handleRequest: (T) -> R) = actor<T> {
for (request in channel) {
val response = handleRequest(request)
responseChannel.send(response)
// Rate limiting logic here
delay(someTime)
}
}
marstran
02/11/2019, 3:44 PMmarstran
02/11/2019, 3:44 PMZargorNET
02/11/2019, 3:51 PMmarstran
02/11/2019, 3:53 PMZargorNET
02/11/2019, 3:58 PM//"client"
suspend fun doReq(req: Request): Response{
//Add request to the queue and return when the request has been made
}
//CALLING
async {client.doReq(/** data **/)}.await()
marstran
02/11/2019, 4:04 PMdata class Request<T, R>(val req: T, responseChannel: Channel<R>)
. The actor can then respond on the request's channel: val response = handleRequest(request.req)
request.responseChannel.send(response)
The doReq
function could then be implemented like this: val rateLimiter = scope.rateLimiter {
// Implement request here..
}
suspend fun <T, R> doReq(req: T): R {
val responseChannel = Channel()
rateLimiter.send(Request(req, responseChannel))
return responseChannel.receive()
}
ZargorNET
02/11/2019, 4:08 PMZargorNET
02/11/2019, 4:09 PMmarstran
02/11/2019, 4:10 PMmarstran
02/11/2019, 4:11 PMZargorNET
02/11/2019, 4:12 PMmarstran
02/11/2019, 4:12 PMNikky
02/12/2019, 12:17 AMZargorNET
02/12/2019, 2:50 PMZargorNET
02/12/2019, 2:52 PMmarstran
02/12/2019, 3:03 PMCompletableDeferred
class that you should use instead of the response channel. You only need a single result. https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-completable-deferred/ZargorNET
02/12/2019, 3:32 PMfun request(req: Request): CompletableDeferred<Response> {
val a = CompletableDeferred<Response>()
a.complete(httpClient.newCall(req).execute())
return a
}
fun call() {
val req = Request.Builder().url("url").build()
runBlocking {
request(req).await()
}
}
(just an example code)