async && await In Kotlin-Coroutines
Tags: kotlin, coroutines, android
Published: 2021-07-23 08:48:18

Before Getting Started I Suggest You Understand What's Actually Coroutine Jobs Are, Which I Have Discussed In The [Previous Blog](https://dev.to/saketh/coroutine-jobs-in-kotlin-2fah). And `Make Sure` That You Have **Included Coroutines Dependency** If It's Not Included:
```
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
```

### Case Scenario

- You May Already Know That When You Have Implemented Respective Codeblock In Your Code It Will Execute Sequentially.

- In Other Words, They'll Be Executed One-By-One By Default.

- But In Few Cases, You May Need To Start The **`Execution Of Multiple Codeblocks At A Time`** Where Output || Result Timing May Vary.

- In Those Case Scenario's You Need To Work **Asynchronously** With Your Respective Codeblock Which Means You Need To Start Those Codeblock's Execution At A Time.

> Asynchronous = Running Multiple Codeblocks At A Time Where Result || Output Will Be Returned || Executed Later On.

### Introduction To *async*

- Now, As I Mentioned Earlier That If You Want To Start Executing At A Time Then You Should Work Asynchronously.

- In Kotlin, We Have Something Known As **`async`** Which Is Of Type ***Deferred*** From Which We Can Build Our Respective Codeblock Asynchronously.

- **`async`** **Doesn't** Return A Job Which Is Also A Coroutine Builder.

- As You Can See Below That **`async`** Is Of Type ***Deferred***:
![defferd.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1627029478566/qpJLpAs5v.png)
![deferred expand.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1627029491213/6vdf38kSI.png)


### Introduction To *await*

- As I Mentioned Above That `async` Will Help You To Work Asynchronously But It May Stop Other Execution Too🤷🏼‍♂️.

- To Avoid That And We'll Be Using `await` Method With `async` So That Remaining Codeblock Execution Will Be Normal.

> In Other Words, **`await` Ensures That The Execution Will Go Further** Until The Function Is Executed Completely.

### Use Case Scenario's

- As You Can See That I Have Created 2 Suspend Functions Through IO Dispatcher:

```
private suspend fun apiCall1() {

}

private suspend fun apiCall2() {
        
}
```

- And I'll Be Delaying For 2 Seconds And Returning A String In Both Functions Respectively:

```
private suspend fun apiCall1(): String {
        delay(2000L)
        return "Html Is A Programming Language🤭"
    }

    private suspend fun apiCall2(): String {
        delay(2000L)
        return "Stay Safe😷"
    }
```

#### Case 1

> Code **Without** Asynchronous

- I'll Implement These Both Suspend Functions In A Coroutine With `GlobalScope` And With *`launch`* Coroutine Builder Through IO Dispatcher:

```
GlobalScope.launch(Dispatchers.IO) {
   Log.d("async-await", apiCall1())
   Log.d("async-await", apiCall2())
}
```

- Now If You'll Launch The Application After Successful Build You'll Notice That **It Takes 4 Seconds To Log Those Messages** Which I Have Given.

- It's Because `apiCall1()` And `apiCall2()` Suspend Functions Delays `2 Seconds Respectively` Before Returning Those Values.

- If You Want To Measure The Time Taken To Complete Those Executions We Have Few Classes || Methods. In My Case,

- I'll Be Using `measureTimeMillis{...}` Which Returns Us The Time Taken To Complete The Execution Which We Have Implemented In That Particular Method || Class In Milliseconds Format.

- You Can Use `measureTimeMillis{...}` In A Variable So That You Can Get The Duration Of That Execution:
```
val time = measureTimeMillis{
// Codeblock
}
```
- Now Let's Add Those Suspend Functions In `time` Variable In Order To Get The Time Taken To Complete The Execution.

```
GlobalScope.launch(Dispatchers.IO) {
  val time = measureTimeMillis {
              Log.d("async-await", apiCall1())
              Log.d("async-await", apiCall2())
       }
              Log.d("async-await", "Time Taken To Complete-> $time ms.")
}
```
- And As You Can See That It Took 4 Seconds To Complete:

![without async and await.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1626954016297/l6cAY0oqY.png)

- It's Because We Are Not Executing Our Code Asynchronously, So It Executes Sequentially By Default.


#### Case 2

> Coding Asynchronously

- Make Sure That You Have Added `async{...}` To Work Asynchronously.

- Coding Asynchronously **Doesn't** Make Your Codeblock To Cook The Result Primarily, It Makes Sure That Your Particular Codeblock Will Be Executed Primarily Rather Than The Result || Output.

- I'll Be Implementing Both Of The Suspend Functions In Two Different Variables With `async` In A Coroutine For Demonstration:

```
GlobalScope.launch(Dispatchers.IO) {
val apiCall1 = async { apiCall1()}
val apiCall2 = async { apiCall2() }
}
```

##### Now, It's The Moment Of Truth🔥.

- Let's Implement Our Above Code BLock Where We Are Working Asynchronously In `measureTimeMillis{...}` So That We Can Get The Duration Of The Execution.

- And Make Sure That You Have Implemented `await()` Method With our Variables So That Remaining Codeblock [If Any] Execution Will Be Normal Without Any Problem(s):

```
GlobalScope.launch(Dispatchers.IO) {
       val apiCall1 = async { apiCall1()}
       val apiCall2 = async { apiCall2() }
       val time = measureTimeMillis {
        Log.d("async-await", apiCall1.await())
        Log.d("async-await", apiCall2.await())
}
        Log.d("async-await", "Time Taken To Complete-> $time ms.")
}
```

- And As You Can See That Both Of The Suspend Functions Are Executed Simultaneously, Which Means Execution Is Now Completed In 2 Seconds Itself:

![async and await.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1626956464022/a0oq6867G.png)

- Well, As You Can See That It Worked Asynchronously🤙🏼.

### Tips [Kinda]

- As I Mentioned Earlier That `async` Is Also A Coroutine Builder That Means You Can Use `async` Instead Of `launch` If You Want To Work Asynchronously. But The Example I Have Given Above Doesn't Make Sense If I Launch A Coroutine With `async`.

- *`launch`* and *`async`* handle exceptions differently. Since async expects An Eventual Call To await, It Holds Exceptions And Rethrows Them As Part Of The await Call. This Means If You Use async To Start A New Coroutine From A Regular Function, You Might Silently Drop An Exception. These Dropped Exceptions **won't appear** In Your Crash Metrics or Be Noted In Logcat.

> In Other Words,

- Make Sure That You Are Handling `async` Properly Because If You Aren't Handling It Properly Errors May Occur.

> `Well, That's All For Now🙌`

>  **`Bye🤗`**