Another promise library for Kotlin (on JVM).
Install via JitPack. For example, add dependency in build.gradle
:
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
compile 'com.github.kmxz:Votive:release-SNAPSHOT'
}
-
Only one existing promise implementation in Kotlin, which is quite complicated. In addition, its API diverses too much from promise implementations in JavaScript.
-
Existing promise implementations on JVM followed the practice of "rejecting by throwing". This is, however, not favored (see "Differences from Promise/A+" section below).
For details, you may read KDoc inside the code.
Class Votive<V, R>
take two type parameters, where V
is value type (when fulfilled/resolved), R
is the reason type (when rejected). It corresponds to Promise
in JavaScript.
Votive(executor: (((V) -> Unit, (R) -> Unit) -> Unit))
. Exactly the same asPromise
constructor in JavaScript.
all(iterable: Iterable<Votive>): Votive
. Exactly the same asPromise.all
in JavaScript.race(iterable: Iterable<Votive>): Votive
. Exactly the same asPromise.race
in JavaScript.resolve(value: V): Votive
. Exactly the same asPromise.resolve
in JavaScript.resolve(votive: Votive): Votive
. Exactly the same asPromise.resolve
in JavaScript.reject(reason: R): Votive
. Exactly the same asPromise.reject
in JavaScript.
thenSimple(onFulfilled: (V) -> Vout): Votive<Vout, R>
. Similar asPromise.prototype.then
in JavaScript.then(onFulfilled: (V) -> Votive<Vout, R>): Votive<Vout, R>
. Similar asPromise.prototype.then
in JavaScript.thenSimple(onFulfilled: (V) -> Vout, onRejected: (R) -> Vout): Votive<Vout, Rout>
. Similar asPromise.prototype.then
in JavaScript.then(onFulfilled: (V) -> Votive<Vout, Rout>, onRejected: (R) -> Votive<Vout, Rout>): Votive<Vout, Rout>
. Similar asPromise.prototype.then
in JavaScript.catchSimple(onRejected: (R) -> V): Votive<V, R>
. Similar asPromise.prototype.catch
in JavaScript.catch(onRejected: (R) -> Votive<V, Rout>): Votive<V, Rout>
. Similar asPromise.prototype.catch
in JavaScript.
Use "simple" methods is you are not rejecting anyway; use methods without "simple" if you may reject the promise by returning a rejected promise.
fun setTimeout(runnable: () -> Unit, delay: Int) {
Thread {
Thread.sleep(delay.toLong())
runnable()
}.start()
}
fun main(args : Array<String>) {
val p1 = Votive<String, String>({ res, rej -> setTimeout({ res("[p1]") }, 600) })
val p2 = Votive<String, String>({ res, rej -> setTimeout({ rej("[p2]") }, 1000) })
val p3 = Votive<String, String>({ res, rej -> setTimeout({ res("[p3]") }, 1800) })
val p4 = Votive<String, String>({ res, rej -> setTimeout({ res("[p4]") }, 200) })
Votive.race(listOf(p1, p2, p3, p4)).thenSimple(::println)
Votive.all(listOf(p1, p2, p3, p4)).thenSimple<Unit, Unit>(::println, ::println)
p3.then({ Votive.reject<String, String>("Oops") }).catchSimple { it + "Really?" }.thenSimple(::println)
}
-
As mentioned above, "rejecting by throwing" is not allowed. Any throws will not be caught. To reject, use the trick of returning
Promise.reject(reason)
instead ofthrow reason
. Reasons:- In JVM, exceptions are expensive.
- Unlike in JavaScript where anything can be thrown, JVM only allows throwing subclasses of
Throwable
. - If "rejecting by throwing" is used, the business logic (rejects) and software error (throws) are mixed together.
- If "rejecting by throwing" is used, the rejection callback (
onRejected
) has to takeThrowable
as parameter, instead of a more specific type.
-
The rule of "
onFulfilled
oronRejected
must not be called until the execution context stack contains only platform code" will NOT be respected. They will be called immediately on the thread which resolve/reject is done. Reasons:- It's caller's own responsibility to take care of executing order.
- On JVM, there are no reliable way to put off callbacks appropriately without affecting portability.
Unlike some promise libraries who automatically execute asynchronous tasks on new threads, this library does not create new threads automatically. This is because some libraries for specific tasks already take care of creating threads.
However, this library itself it totally thread-safe. In other words, you can share a votive (promise) across threads and do whatever you want.