Promises with Kovenant 

Another option to write asynchronous code is to use promises. A promise is similar to a future (in many frameworks, futures and promises are synonymous), as it represents a computation that may complete in the future. We have a blocking method to obtain its result, but we can also react to its result, callback style. 

Kovenant (http://kovenant.komponents.nl/) is an implementation of promises for Kotlin:

import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.task
import nl.komponents.kovenant.then

class
PromiseUserService(private val userClient: UserClient,
private val factClient: FactClient,
private val userRepository: UserRepository,
private val factRepository: FactRepository) : UserService {

override fun getFact(id: UserId): Fact {

return (task {
userRepository.getUserById(id)
} then { user ->
if (user == null) {
task {
userClient.getUser(id)
} success { userFromService ->
userRepository.insertUser(userFromService)
} then { userFromService ->
getFact(userFromService).get()
}
} else {
task { factRepository.getFactByUserId(id) ?: getFact(user).get() }
}
}).get().get()
}

private fun getFact(user: User): Promise<Fact, Exception> = task {
factClient.getFact(user)
} success { fact ->
factRepository.insertFact(fact)
}
}

The function task creates Promise<T, Exception> (something that we didn't cover previously in our other implementations). We can interact with Promise<T, Exception> in several ways:

  • get(): T: This blocks the current thread and returns the promise's result.
  • then(bind: (T) -> R): Promise<R, Exception>: This is similar to map on functional collections; it returns a new Promise value with a new type.
  • success(callback: (T) -> Unit): Promise<T, Exception>: This is callback on successful Promise execution. It's useful for side effects
  • fail(callback: (Exception) -> Unit): Promise<T, Exception>: This is callback on fail, like a catch block.
  • always(callback: () -> Unit): Promise<T, Exception>: This always executes, like a finally block.

The codes feel difficult to grasp at first sight, but, once you get used to the promise idioms, it is easy to read. Also, notice that a promise is a future, so you can write something similar to our future's example but without messing around with Executors. Java 8 includes a new type of future named CompletableFuture<T> which can be considered a promise.

Execution time is around 1,350 milliseconds for the first execution (Kovenant initialization phase), and then it stabilizes around 1,200 milliseconds. On its default configuration, Kovenant uses as many threads as possible, resulting in a high use of memory, but Kovenant can be fine-tuned to use fewer threads.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.144.248