/
πŸ“™

JS async/await

JavaScript
Table of contents

async / await λ₯Ό μ‚¬μš©ν•˜λ©΄ ν”„λ‘œλ―ΈμŠ€λ₯Ό 더 νŽΈν•˜κ²Œ μ‚¬μš©ν•  수 있고, 가독성이 쒋아진닀.

async

async ν‚€μ›Œλ“œλŠ” function ν‚€μ›Œλ“œμ™€ ν•¨κ»˜ async function ν‚€μ›Œλ“œλ‘œ μ‚¬μš©ν•˜μ—¬ AsyncFunction 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•˜λ‚˜μ˜ 비동기 ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜κ³ , μ•”λ¬΅μ μœΌλ‘œ Promiseλ₯Ό μ‚¬μš©ν•˜μ—¬ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

javascript
// async function μ„ μ–Έ
async function asyncFuncDeclare() {
return /* ... */;
}
// async function ν‘œν˜„μ‹ (ES6 ν™”μ‚΄ν‘œ ν•¨μˆ˜ 문법)
const asyncFuncExpression = () => {
return /* ... */;
};

항상 Promiseλ₯Ό λ°˜ν™˜ ν•œλ‹€

asyncκ°€ 뢙은 ν•΄λ‹Ή ν•¨μˆ˜λŠ” 항상 ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κ³ , ν”„λ‘œλ―ΈμŠ€κ°€ μ•„λ‹Œ 값을 λ°˜ν™˜ν•˜λ”λΌλ„ 이행 μƒνƒœμ˜ ν”„λΌλ―ΈμŠ€(resolved promise)둜 값을 감싸 μ΄ν–‰λœ ν”„λΌλ―ΈμŠ€κ°€ λ°˜ν™˜λ˜λ„λ‘ ν•œλ‹€.

javascript
async function func() {
return 1;
}
func().then(alert); // 1

λͺ…μ‹œμ μœΌλ‘œ ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” 것도 κ°€λŠ₯ ν•˜μ§€λ§Œ κ²°κ³ΌλŠ” λ™μΌν•˜λ‹€.

javascript
async function func() {
return Promise.resolve(1);
}
func().then(alert); // 1

await

await ν‚€μ›Œλ“œλŠ” Promiseκ°€ 처리될 λ•ŒκΉŒμ§€ 기닀리기 μœ„ν•΄ μ‚¬μš©ν•˜λŠ” μ—°μ‚°μžλ‹€. async function λ‚΄λΆ€μ—μ„œλ§Œ μ‚¬μš©ν•  수 있고, ν”„λ‘œλ―ΈμŠ€κ°€ 처리되면 κ·Έ 결과와 ν•¨κ»˜ 싀행이 μž¬κ°œλœλ‹€.

awaitλŠ” λ‹€μŒμ— μ˜€λŠ” 문의 값이 ν”„λ‘œλ―ΈμŠ€κ°€ μ•„λ‹ˆλ©΄ ν•΄λ‹Ή 값을 resolved Promise둜 λ³€ν™˜μ‹œν‚¨λ‹€.

Promise 처리λ₯Ό κΈ°λ‹€λ¦°λ‹€

awaitλ₯Ό λ§Œλ‚˜λ©΄ ν”„λ‘œλ―ΈμŠ€κ°€ 처리(settled)될 λ•ŒκΉŒμ§€ 기닀리고 κ²°κ³ΌλŠ” κ·Έ 이후 λ°˜ν™˜λœλ‹€.

ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , ν•¨μˆ˜ 본문이 μ‹€ν–‰λ˜λŠ” 도쀑에 싀행이 μž μ‹œ 'μ€‘λ‹¨β€™λ˜μ—ˆλ‹€κ°€ ν”„λ‘œλ―ΈμŠ€κ°€ 처리되면 싀행이 μž¬κ°œλœλ‹€.

javascript
async function func() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("μ™„λ£Œ!"), 1000)
});
let result = await promise; // ν”„λΌλ―ΈμŠ€κ°€ 이행될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
alert(result); // "μ™„λ£Œ!"
}
func();

ν”„λ‘œλ―ΈμŠ€ μ²˜λ¦¬κ°€ μ„±κ³΅ν•˜λ©΄ awaitλŠ” fulfill 된 ν•΄λ‹Ή 값을 λ¦¬ν„΄ν•˜κ³ , μ‹€νŒ¨ν•˜λ©΄ awaitλŠ” reject 된 값을 throwν•œλ‹€.

ν”„λ‘œλ―ΈμŠ€κ°€ 처리되길 κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆμ—” 엔진이 λ‹€λ₯Έ 일(λ‹€λ₯Έ 슀크립트λ₯Ό μ‹€ν–‰, 이벀트 처리 λ“±)을 ν•  수 μžˆμ–΄ CPU λ¦¬μ†ŒμŠ€ λ‚­λΉ„λ₯Ό 쀄일 수 μžˆλ‹€.

μ—λŸ¬ 핸듀링

ν”„λ‘œλ―ΈμŠ€κ°€ reject 되면 throw문을 μž‘μ„±ν•œ κ²ƒμ²˜λŸΌ μ—λŸ¬κ°€ λ˜μ Έμ§„λ‹€.

javascript
async function func() {
await Promise.reject(new Error("μ—λŸ¬ λ°œμƒ!"));
}

μœ„μ˜ μ½”λ“œλŠ” μ•„λž˜μ˜ μ½”λ“œμ™€ λ™μΌν•˜λ‹€.

javascript
async function func() {
throw new Error("μ—λŸ¬ λ°œμƒ!");
}

ν”„λ‘œλ―ΈμŠ€κ°€ reject 되기 전에 μ‹œκ°„μ΄ κ±Έλ¦¬λ©΄μ„œ awaitκ°€ μ—λŸ¬λ₯Ό throw ν•˜λŠ” 것에 λ”œλ ˆμ΄κ°€ λ°œμƒν•˜λŠ” 경우, try..catchλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

javascript
async function func() {
try {
let response = await fetch('...');
let data = await response.json();
} catch(err) {
// fetch와 response.jsonμ—μ„œ λ°œν–‰ν•œ μ—λŸ¬ λͺ¨λ‘λ₯Ό μ—¬κΈ°μ„œ μž‘λŠ”λ‹€.
alert(err);
}
}
func();

μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ μ œμ–΄ 흐름이 catch λΈ”λ‘μœΌλ‘œ λ„˜μ–΄κ°€κ³ , μ—¬λŸ¬ μ€„μ˜ μ½”λ“œλ₯Ό try둜 κ°μ‹ΈλŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

.catch만 μ‚¬μš©ν•΄ async function μ™ΈλΆ€μ—μ„œ reject 된 ν”„λ‘œλ―ΈμŠ€λ₯Ό μ²˜λ¦¬ν•  μˆ˜λ„ μžˆλ‹€.

javascript
async function func() {
let response = await fetch('...');
}
func().catch(alert);

async/await 와 promise.then/catch

async/await을 μ‚¬μš©ν•˜λ©΄ awaitκ°€ λŒ€κΈ°λ₯Ό μ²˜λ¦¬ν•΄μ£ΌκΈ° λ•Œλ¬Έμ— .then을 μ‚¬μš©ν•  일이 거의 μ—†κ³ , .catch λŒ€μ‹  일반 try..catchλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€λŠ” μž₯점이 생긴닀. ν•˜μ§€λ§Œ asyncν•¨μˆ˜ λ°”κΉ₯의 μ΅œμƒμœ„ 레벨 μ½”λ“œμ—μ„  awaitλ₯Ό μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ— μœ„μ˜ μ½”λ“œ 처럼 .then/catchλ₯Ό μΆ”κ°€ν•΄ μ΅œμ’… κ²°κ³Όλ‚˜ μ²˜λ¦¬λ˜μ§€ λͺ»ν•œ μ—λŸ¬λ₯Ό 닀룬닀.

일반 ν•¨μˆ˜μ—λŠ” awaitλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€

일반 ν•¨μˆ˜μ—μ„œ await을 μ‚¬μš©ν•˜λ©΄ 문법 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

javascript
function func() {
let promise = Promise.resolve(1);
let result = await promise; // Syntax error
}

μ΅œμƒμœ„ 레벨 μ½”λ“œμ—μ„œ μž‘λ™ν•˜μ§€ μ•ŠλŠ”λ‹€

μ΅œμƒμœ„ 레벨 μ½”λ“œ(top-level code)μ—μ„œ awaitλŠ” μ‚¬μš©ν•  수 μ—†λ‹€.

javascript
// μ΅œμƒμœ„ 레벨 μ½”λ“œμ—μ„  문법 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.
let response = await fetch('...');
let data = await response.json();

ν•˜μ§€λ§Œ 읡λͺ… async ν•¨μˆ˜λ‘œ μ½”λ“œλ₯Ό 감싸면 μ΅œμƒμœ„ 레벨 μ½”λ“œμ—λ„ awaitλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

javascript
(async () => {
let response = await fetch('...');
let data = await response.json();
...
})();

async 클래슀 λ©”μ„œλ“œ

λ©”μ„œλ“œ 이름 μ•žμ— asyncλ₯Ό μΆ”κ°€ν•˜λ©΄ async 클래슀 λ©”μ„œλ“œλ₯Ό μ„ μ–Έν•  수 μžˆλ‹€.

javascript
class Waiter {
async wait() {
return await Promise.resolve(1);
}
}
new Waiter()
.wait()
.then(alert); // 1

async λ©”μ„œλ“œμ™€ async ν•¨μˆ˜λŠ” ν”„λΌλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κ³  awaitλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€λŠ” 점이 λ™μΌν•˜λ‹€.

thenable 객체λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€

promise.then처럼 await에도 thenable 객체(then λ©”μ„œλ“œκ°€ μžˆλŠ” 호좜 κ°€λŠ₯ν•œ 객체)λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. μ„œλ“œνŒŒν‹°μ—μ„œ 받은 객체가 .then을 μ§€μ›ν•˜λ©΄ 이 객체λ₯Ό await와 ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆλ‹€.

thenable 객체

μ„œλ“œνŒŒν‹° 객체가 ν”„λ‘œλ―ΈμŠ€κ°€ μ•„λ‹ˆμ§€λ§Œ ν”„λ‘œλ―ΈμŠ€μ™€ ν˜Έν™˜ κ°€λŠ₯ν•œ 객체λ₯Ό μ œκ³΅ν•  수 μžˆλ‹€λŠ” μ μ—μ„œ 생긴 κΈ°λŠ₯

awaitλŠ” .then이 κ΅¬ν˜„λ˜μ–΄μžˆμœΌλ©΄μ„œ ν”„λΌλ―ΈμŠ€κ°€ μ•„λ‹Œ 객체λ₯Ό λ°›μœΌλ©΄, λ‚΄μž₯ ν•¨μˆ˜ resolve와 rejectλ₯Ό 인수둜 μ œκ³΅ν•˜λŠ” λ©”μ„œλ“œμΈ .then을 ν˜ΈμΆœν•œλ‹€(일반 Promise executorκ°€ ν•˜λŠ” 일과 동일).

μš”μ•½

  • async ν‚€μ›Œλ“œλŠ” function ν‚€μ›Œλ“œμ™€ ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ async ν•¨μˆ˜λ₯Ό μ •μ˜ν•œλ‹€.

  • asyncκ°€ 뢙은 ν•¨μˆ˜λŠ” λ°˜λ“œμ‹œ ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κ³ , ν”„λ‘œλ―ΈμŠ€κ°€ μ•„λ‹Œ 경우 ν”„λ‘œλ―ΈμŠ€λ‘œ 감싸 λ°˜ν™˜ν•œλ‹€.

  • awaitλŠ” Promiseκ°€ 처리될 λ•ŒκΉŒμ§€ 기닀리기 μœ„ν•΄ μ‚¬μš©ν•˜λŠ” μ—°μ‚°μžλ‹€.

  • async function λ‚΄λΆ€μ—μ„œ 만 awaitλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

  • await은 ν”„λ‘œλ―ΈμŠ€κ°€ μ„±κ³΅ν•˜λ©΄ ν”„λΌλ―ΈμŠ€ 객체의 result 값을 λ°˜ν™˜ν•˜κ³ , μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ throwν•œλ‹€.

ν•œ 쀄 μš”μ•½

async / awaitλŠ” ν”„λ‘œλ―ΈμŠ€λ₯Ό 기반으둜 ν•˜κ³ , 비동기 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄μ„œ μ΄ν•΄ν•˜κΈ° 쉽고 읽기 νŽΈν•˜κ²Œ λ§Œλ“€μ–΄ μ€€λ‹€.

reference

async function ν‘œν˜„μ‹ - JavaScript | MDN

AsyncFunction - JavaScript | MDN

async function - JavaScript | MDN

await - JavaScript | MDN

async와 await | javascript.info

logo
Things I've Learned