# Asynchronous Programming In Javascript - Async & Await

# 1\] Async Fuctions

### 1) 정의

Async & Await은 비동기 함수를 동기 함수처럼 코드를 짜게 해주는 문법(통사적 특징, syntactic feature)이라고 할 수 있다.

### 2) Async

Async를 함수에 쓰게 되면 비동기 함수가 된다.

비동기 함수는 event loop에서 비동기적으로 동작하는 함수이다.

**Example**

```javascript
async function f() {
    // code
}
```

### 3) Async의 리턴

Async function은 항상 Promise를 리턴한다.

만약 함수가 Promise를 리턴하지 않고 value만 리턴하면, Javascript는 자동적으로 Promise로 래핑한다.

따라서 값일 경우에는 같은 값을 가진 fulfilled Promise를 리턴한다.

![](https://blogger.googleusercontent.com/img/a/AVvXsEg2vl01ZzDkar6uI2m6SuCoh50x5nGfDwPUVaA3wzIZ-K9deaAiXIN_fgjB4dRNKRxraWkoELu834Q80SiM97cSXj5jxY3LlvYUzcJSu578W9ROBG_uqGNW0ycqfSXKQW-0pceu0ybFe8O15Bq3n5IkJ50oANXzKiqoCcjPzR0_mH6nrK7PTwWeDw8w2mWN align="left")

이미 Promise를 리턴하고 있으면, 변화(modification) 없이 그대로 리턴한다.

![](https://blogger.googleusercontent.com/img/a/AVvXsEgH8YjZmYSViOq-xRqasSMKS5AcoYe9Mek7JxsN4_H4yy3EthYKg9Jz8ZxATVV5zpu2gw1K5RjOR6VHpw7i-HnTvBojoza-Mss85-mrHotT2hO7HiTcNwHnRBw_1e7oVADXFcfg_0FJHukP5cFbgTMGm2zDjFQnIl9cGxtjKzP_n7G5A-sbd9c5BEQ8pnYk=w341-h324 align="left")

3초 뒤에 fulfilled되는 Promise를 리턴할 경우, 3초 전에 pending이었다가 3초 후에 fulfilled가 되는 모습을 볼 수 있다.

# 2\] Await Keyword

await은 일반 function에 사용할 수 없고, async function에만 사용 가능하다.

await은 Promise가 resolved되거나 rejected가 되는 것에 상관 없이 settled 될 때까지 기다릴 때 사용한다.

중요한 점은 Promise를 기다리므로, Promise는 pending 상태가 아니게 된다는 것이다.

**Example**

```javascript
function getOne() {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(1), 3000);
    });
}

async function f() {
    const num = await getOne();
    console.log(num);
}

f();
```

이렇게 코드를 짤 경우 3초 뒤에 1이 나오게 된다.

따라서 f()는 getOne()에서 Promise가 resolved되거나 rejected 될 때까지 기다린다는 것을 알 수 있다.

Promise가 resolved가 되면 값을 num 변수에다가 할당하게 된다.

그러나 이것은 **전체 어플리케이션이 이 함수가 resolved 될 때까지 멈춘다는 것은 아니다.**

Javascript engine은 이 함수가 멈춘 동안에 다른 함수나 이벤트를 처리할 수 있다.

**Async Await을 사용하여, 기존의 Promise를 사용하는 함수를 쉽게 대체할 수 있다.**

###### **Example)** 기존 Promise처럼 사용하려면 다음과 같이 사용 가능하다.

```javascript
function f() {
    getOne()
        .then(num => console.log(num));
}
```

# 3\] Async Await의 사용

Promise를 사용한 코드와 비교해 보았을 때, 기본적으로 then을 사용한 모든 부분에 await을 써주면 된다.

**Example)** Promise 사용

```javascript
function getFetch() {
	fetch('https://www.~~~') // url
		.then(response => response.json())
		.then(value => console.log(value.message));
}
```

**Example)** Async Await 사용

```javascript
async function getFetch() {
	let response = await fetch('https://www.~~~');  // url
	let value = await response.json();
	console.log(value.message));
}
```

# 4\] Top Level Await

브라우저가 아닌 Node.js에서, ECMAscript module이 아닐 경우 await은 top level에 적용할 수 없다.

**Example)** 브라우저일 때

![](https://blogger.googleusercontent.com/img/a/AVvXsEgDIhIZrZeWB_rcNGcf3Y5OO0_d7reeMdPBZjFz0SOnt7Tn0kg-UR51abZWwClXrcvJuDrRdwAtVnnyQZEaLuVyGqwWEVdh9l-NvJ2quryLsG-JgZlqzzA0s9wuuXzQmn1lJe-mM1nDhroDkM1YNlhjl35lShNP_jRgVGJCq9mybBeIxIyDNH9-Q1CxcHZB align="left")

**Example)** Node.js일 때(ECMAscript module이 아닐 때)

![](https://blogger.googleusercontent.com/img/a/AVvXsEjoglvamUBgoD0t6LiO5gT3t6c9CGGn7W6lND6OlmhUyy0TePDEAYeunLLwKBoRhqyH-Fxyb-m_8CsAUkl3NOV1XvUO8NPJdWCM42KHWEQ4riuEd46dH3IjMEZKjKD36wOEPe4yoL3q2rdlSQqz-RMLB9_I307IfpQM-L3qjRyEQQ2Ps6CNjclCSNTtVvxB=w538-h190 align="left")

**package.json에 "type": "module"을 사용하거나, mjs파일로 만들면 실행 가능하다.**

# 5\] Handling Errors

### 1) 전통적인 try catch 사용

Async Await은 try catch를 사용할 수 있다.

![](https://blogger.googleusercontent.com/img/a/AVvXsEg270di2fLFddgSso8jcfsI-wH2mrDMSXzDWj_XNF32kqsgJF8qZ9x-533oPhFRUVXIp9l62MDQpiBEVE6BJ8hSQQfl7y4eisq4ixn-z3yNtIORhSHfFYSR7nCknlOzdSenEolja0j54LaLR_o0Ab3X8SmR1PwpXui29_KN1Ik4zETpMSlPyM28kLAvOa0m=w420-h225 align="left")

### 2) then 또는 catch 사용

async function은 항상 Promise를 리턴하므로, then이나 catch를 사용할 수 있다.

![](https://blogger.googleusercontent.com/img/a/AVvXsEhoWfo_r7wjPARl88h-_oe_eZC_UI4_iwdfrNm_FQUZJJnE-H6w4CNL2SAw0JadM2O8isWkkOzDvD-M8cdSrHKfk0JggNsPY4m4wO7TzsI8AZxcQE6i1WticpMStxhN5TMP_JAfrX530xiN9ipopS2I_2-YHukrW6uBClL1iHEUQnWKKC5E19RBUjME3eZy=w423-h174 align="left")

## Further Details

#### handle function을 통한 최신 비동기 로직 코드

```javascript
// handle 함수 생성
const handle = async (promise) -> {
    try {
        const data = await promise;
        return [data, undefined];
    } catch (error) {
        return [undefined, error];
    }

}

// 사용
const [response, error] = await handle(비동기 함수);
if (error) {
    alert("Error occurred!");
    return;
}

// 추후 response 사용
```

# 6\] Sequential and Parallel Execution

### 1) 순차적(Sequential) 실행

Async Await을 그냥 사용하게 되면, 순차적으로 실행이 된다.

**Example**

```javascript
function getOne() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('one');
			resolve(1);
		}, 3000);
	});
}

function getTwo() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('two');
			resolve(2);
		}, 3000);
	});
}

async function f() {
	const one = await getOne();
	const two = await getTwo();
	console.log(one, two);
}

f();
```

3초후 1이 나오고, 2초 후 2가 나오게 된다.

### 2) 병렬적(Parallel) Execution

함수가 아닌 response에 await을 사용하면 된다.

Promise.all과 같다.

**Example**

```javascript
function getOne() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('one');
			resolve(1);
		}, 3000);
	});
}

function getTwo() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('two');
			resolve(2);
		}, 3000);
	});
}

async function f() {
	const response1 = getOne();
	const response2 = getTwo();
        const one = await response1;
        const two = await response2;
	console.log(one, two);
}

f();
```

3초후 1과 2가 같이 나오게 된다.

### Further Details

f()를 리팩토링하면 다음과 같이 사용할 수도 있다.

**Example)** response를 한 번에 할당

```javascript
async function f() {
	const response1 = getOne();
	const response2 = getTwo();
        const [one, two] = [await response1, await response2];
	console.log(one, two);
}
```

**Example)** console.log에 직접 입력

```javascript
async function f() {
	const response1 = getOne();
	const response2 = getTwo();
	console.log(await response1, await response2);
}
```
