Skip to content

An object to make asynchronous calls easy across platform

License

Notifications You must be signed in to change notification settings

aSoft-Ltd/later

Repository files navigation

Later

badge badge badge badge badge badge badge badge badge badge

Introduction

Heavily inspired by javascript promises, Later( s) are mainly here to ease the bridge between kotlin coroutines for multiplatform and their respective platforms.

Problem Statement

While it is true that kotlin can compile down to (js,jvm or native). Usually there are some limitations. One of the heaviest ones are usually trying to call suspend functions from other platforms (mostly Java and Javascript).

A Later, comes in handy as it lets you work with suspend functions from kotlin, promises from javascript and also Futures from Java. All you have to do is return a Later object and you are good to go.

Samples

In Kotlin you can do something like this

class TokenService(val scope: CoroutineScope) {
    fun getToken(id: String) = scope.later { // this is a suspending labda
        delay(100) // simulating heavy work
        getUserTokenFromServer() // returned result will be the valued that will be Later delivered to you upon completion
    }
}

Notice that getToken doesn't have to be a suspend function. Which means, it is callable from Java and Javascript. Even C

In Javascript, a Later is a Thenable

meaning you can chain then, catch and finally methods as you would

const tokenService = require('your-published-shared-lib');

tokenService.getUser("user-1")
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.catch(failureCallback)
.finally(finalState => {
  console.log(`Got the final result: ${finalState}`);
});

But since a Thenable is never really fully a Promise, We have provided a way that you can easily convert a Later to a Promise like so

const tokenService = require('your-published-shared-lib');

tokenService.getUser("user-1").asPromise()   // notice asPromise() here
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.catch(failureCallback)
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
});

Using the same kotlin code in java, is piece of cake

import your.published.shared.lib.TokenService;

class Test {
    TokenService tokenService = TokenService.getDefault();

    public static void testLater() {
        tokenService.getToken("user-1")
                .then(result -> doSomethingElse(result))
                .then(newResult -> doThirdThing(newResult))
                .error(failureCallback) // notice it is error instead of catch (catch is a reserved keyword in java)
                .complete(finalState -> {
                    console.log("Got the final result: " + finalState);
                    return null;
                });
    }
}

as normal, if you are well versed to using CompletableFutures and like that, there is a convenient method asCompletableFuture() that returns a CompletableFuture backed by the Later

Setup

dependencies {
    implementation("tz.co.asoft:later-core:0.0.63")

    implementation("tz.co.asoft:later-ktx:0.0.63") // if using with kotlinx coroutines
}

Extensions

Later is being made to extend into any Deferred data type. It even has built in integration with Deferred support from kotlinx coroutines

Conclusion

Now, go and build real multiplatform code, that can be shared across mobile, web and server