在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):Shopify/promise-kotlin开源软件地址(OpenSource Url):https://github.com/Shopify/promise-kotlin开源编程语言(OpenSource Language):Kotlin 100.0%开源软件介绍(OpenSource Introduction):Promise.kt
What is Promise ?Wiki defines Promises pattern as:
Technically, it's a wrapper for an async function with result returned via callback. Besides being an async computation wrapper, FeaturesThis implementation of
Quick StartAs a quick start let's imagine the next scenario, we want to fetch user by id first and then fetch user's repositories. Below example that demonstrates how it can be solved with Promise.ofSuccess<Long, IOException>(100)
.then { userId ->
Promise<User, IOException> {
val fetchUser: Call = userService.fetchUserById(userId)
onCancel {
// when Promise.cancel() is called this action will be performed
// to give you a chance cancel task execution and clean up resources
fetchUser.cancel()
}
fetchUser.enqueue(object : Callback {
override fun onFailure(e: IOException) {
// notify promise about error
reject(e)
}
override fun onResponse(response: User) {
// notify promise about success
resolve(response)
}
})
}
}.then { user ->
// chain another promise that will be executed when previous one
// resolved with success
Promise<List<Repo>, IOException> {
val fetchUserRepositories: Call = repoService.fetchUserRepositories(user.id)
onCancel {
// when Promise.cancel() is called this action will be performed
// to give you a chance cancel task execution and clean up resources
// any chained promises will get a chance to cancel their task
// if they alread started execution
fetchUserRepositories.cancel()
}
fetchUserRepositories.enqueue(object : Callback {
override fun onFailure(e: IOException) {
// notify promise about error
reject(e)
}
override fun onResponse(response: List<Repo>) {
// notify promise about success
resolve(response)
}
})
}.map {
// chain implicitly new promise with transformation function
repositories -> user to repositories
}
}.whenComplete {
// subscribe to pipeline of chained promises
// this call will kick-off promise execution
when (it) {
is Promise.Result.Success -> println("User: ${it.value.first} repositories: ${it.value.second}")
is Promise.Result.Error -> println("Yay, error: ${it.error.message}")
}
} Usage
Create promiseThere are 2 ways to create a Promise<User, RuntimeException> {
val fetchUserRequest = ...;
onCancel {
// will be called if promise has been canceled
// it is task responsibility to terminate any internal long running jobs
// and clean up resources here
fetchUserRequest.cancel()
}
// do some real job
val user = fetchUserRequest.execute();
// notify about success
resolve(user)
//or report error
//reject(RuntimeException("Failed"))
} we just created a The second way to create a val promise1 = Promise.of("Boom!")
val promise2 = Promise.ofSuccess<String, RuntimeException>("Kaboom!")
val promise3 = Promise.ofError<String, IOException>(IOException("Smth wrong today"))
Start promiseTo start promise task execution you have to subscribe to it: Promise<String, RuntimeException> {
val call = null
onCancel {
call.cancel()
}
val result = try {
call.execute() // long running job
} catch (e: Exception) {
reject(RuntimeException(e))
return@Promise
}
resolve(result)
}.whenComplete { result:
when (it) {
is Promise.Result.Success -> println("We did it: ${it.value}")
is Promise.Result.Error -> println("Yay, error: ${it.error.message}")
}
} You can call as many Chain promisesNow the best part, you can build a chain or pipeline of promises by using: Promise.ofSuccess<Long, IOException>(100)
.then { userId ->
Promise<User, IOException> {
val fetchUser: Call = userService.fetchUserById(userId)
onCancel {
// when Promise.cancel() is called this action will be performed
// to give you a chance cancel task execution and clean up resources
fetchUser.cancel()
}
fetchUser.enqueue(object : Callback {
override fun onFailure(e: IOException) {
// notify promise about error
reject(e)
}
override fun onResponse(response: User) {
// notify promise about success
resolve(response)
}
})
}
}.then { user ->
// chain another promise that will be executed when previous one
// resolved with success
Promise<List<Repo>, IOException> {
val fetchUserRepositories: Call = repoService.fetchUserRepositories(user.id)
onCancel {
// when Promise.cancel() is called this action will be performed
// to give you a chance cancel task execution and clean up resources
// any chained promises will get a chance to cancel their task
// if they alread started execution
fetchUserRepositories.cancel()
}
fetchUserRepositories.enqueue(object : Callback {
override fun onFailure(e: IOException) {
// notify promise about error
reject(e)
}
override fun onResponse(response: List<Repo>) {
// notify promise about success
resolve(response)
}
})
}.map {
// chain implicitly new promise with transformation function
repositories -> user to repositories
}
} SchedulingEven though it is up to promise task to decide what thread to use for job execution and notify about result, but sometimes as a consumer you need a way to specify explicitly the thread on which you want receive the result: val mainThreadExecutor: Executor = ...;
Promise<User, IOException> {
//do some job
}
.completeOn(mainThreadExecutor)
.whenComplete { result: Promise.Result<User, RuntimeException> ->
when (result) {
is Promise.Result.Success -> println("User : ${result.value}")
is Promise.Result.Error -> println("Yay, error: ${result.error.message}")
}
} Now the result will be delivered on fun <T, E> Promise<T, E>.completeOn(handler: Handler): Promise<T, E> {
return bind { result ->
Promise<T, E> {
val canceled = AtomicBoolean()
onCancel {
canceled.set(true)
}
handler.post {
if (!canceled.get()) {
when (result) {
is Promise.Result.Success -> onSuccess(result.value)
is Promise.Result.Error -> onError(result.error)
}
}
}
}
}
} This a good example of using You can even specify on what thread Promise<User, IOException> {
//do some job
}
.startOn(Executors.newSingleThreadExecutor())
.whenComplete { result: Promise.Result<User, RuntimeException> ->
when (result) {
is Promise.Result.Success -> println("User : ${result.value}")
is Promise.Result.Error -> println("Yay, error: ${result.error.message}")
}
} Now the job inside promise will be started with the executor we just provided. GroupsThere are circunstances where you would like to handle a cluster of promises. Let's imagine we have a list of users ids and we want to know the latest activity for each user.
Gradle Integration
Version Other APIAdditionally this micro-framework provides next util functions:
ContributionsWe welcome contributions. Please follow the steps in our contributing guidelines. License
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论