# Kotlin, Coroutine: Convert Async APIs into Sync

> If get to know something new by reading my articles, don't forget to endorse me on [LinkedIn](https://www.linkedin.com/in/rommansabbir/)

# What is Async and Sync APIs?

**Synchronous/asynchronous APIs** are application programming interfaces that return data for requests either immediately or at a later time, respectively. **Synchronous/asynchronous APIs** provide a way to make immediate or scheduled requests for resources, data or services when available.

The synchronous and asynchronous nature of an **API** is a function of the time frame from the request to the return of data. In the case of synchronous APIs, the expectation is that there will be an immediate return of data. The application requests data and waits for it until a value is returned.

In the case of asynchronous **APIs**, the availability of a resource, service or data store may not be immediate. These **APIs** may provide a callback to the requester when the requested resource is ready. **Asynchronous** requests are useful in maintaining functionality in an application rather than tie up application resources waiting on a request.

An **API** may be synchronous where data or service availability, resources and connectivity are high and low latency is a requirement. An **API** may be asynchronous where data or service availability and connectivity are low or oversaturated with demand.

# How to convert Async APIs into Sync in Kotlin using Coroutine?

\[Kotlin's Coroutine Knowledge is Required for further\]

Kotlin has a lots of modern feature including one `suspendCoroutine`.

```kotlin
suspend inline fun <T> suspendCoroutine(
    crossinline block: (Continuation<T>) -> Unit
): T
```

How it's work?

Obtains the current continuation instance inside suspend functions and suspends the currently running coroutine.

In this function both `Continuation.resume` and `Continuation.resumeWithException` can be used either synchronously in the same stack frame where the suspension function is run or asynchronously later in the same thread or from a different thread of execution. The subsequent invocation of any resume function will produce an `IllegalStateException`. \[Official Doc\]

# Let's deep dive into the coding part

```kotlin
class Worker {
    /*Async API*/
    fun doSomething(listener: Listener, throwError: Boolean) {
        when (throwError) {
            true -> {
                Thread.sleep(3000)
                listener.onError(Exception("Just a random exception..."))
            }
            else -> {
                Thread.sleep(3000)
                listener.onSuccess("Success")
            }
        }
    }

    interface Listener {
        fun onSuccess(msg: String)
        fun onError(e: Exception)
    }
}
```

We have a class `Worker`, where we have a single API `doSomething(listener : Listener, throwError : Boolean)`.

Let's take a look at the function signature, function takes a `Worker.Listener` (Callback) object as a parameter. Client get notified about the work result through the callback `Worker.Listener`.

But, it's an **Asynchronous API** and In certain cases, we might need to execute the **API** in a Synchronous way. So, how to do this?

We can solve this problem with the help of **Kotlin's Coroutine**.

```kotlin
suspend fun Worker.doSomethingSync(throwError: Boolean): String {
    return suspendCoroutine {
        doSomething(object : Worker.Listener {
            override fun onSuccess(msg: String) {
                it.resume("Success")
            }

            override fun onError(e: Exception) {
                it.resumeWithException(e)
            }

        }, throwError)
    }
}
```

Now, we have an `Suspended Extension Function` of `Worker` called `doSomethingSync()`. This API return a `String` object as a `return` type and `throw Exception` if occurs.

So, where is the magic happening?

`doSomethingSync()` return `suspendCoroutine<String>`. Inside the **API**, we are calling the Async API `doSomething()` and pass an Anonymous listener as the callback and when the callback returns events `Success` or `Error`, `Continuation` also return `Success` or `Error`. If the state is `Error`, `doSomethingSync()` throws `Exception`. When we call `doSomethingSync()` **API**, it blocks the current execution and waits for the result from the `doSomethingSync()` in a Sync way.

Example:

```kotlin
class Tester {
    fun test() {
        val worker = Worker()
        /*Async Operation*/

        /*Callback to get notified regarding the result*/
        val listener = object : Worker.Listener {
            override fun onSuccess(msg: String) {
                println(msg)
            }

            override fun onError(e: Exception) {
                e.printStackTrace()
                println(e.message)
            }
        }
        /*Do some work, don't throw exception*/
        worker.doSomething(listener, false)
        /*Do some work, throw exception*/
        worker.doSomething(listener, true)


        /*Async to Sync Operation*/
        CoroutineScope(Dispatchers.Main).launch {
            try {
                /*Do some work, don't throw exception*/
                println(worker.doSomethingSync(false))
                /*Do some work, throw exception*/
                println(worker.doSomethingSync(true))
            } catch (e: Exception) {
                e.printStackTrace()
                println(e.message)
            }
        }
    }
}
```

# Full implementation in Kotlin:

%[https://gist.github.com/rommansabbir/c4c0291c3f36860d4800d96312d739e3] 

%%[linkedin]
