Async await - Lee-hyuna/33-js-concepts-kr GitHub Wiki
Async/await
๋ฒ์ญ : https://javascript.info/async-await
์ฌ๊ธฐ promises์ ํจ๊ป ์๋๋๋ "async/await" ์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ๋ฌธ๋ฒ์ด ์๋ค. ๋งค์ฐ ๋๋๋๋ก ์ดํดํ๊ธฐ์ ์ฌ์ฉํ๊ธฐ๊ฐ ์ฝ๋ค.
Async functions
async
ํค์๋์ ๋ํด์ ์์๋ณด์. ์ด ํค์๋๋ ๋ค์๊ณผ ๊ฐ์ด ํจ์ ์๋ถ๋ถ์ ์์นํ๋ค.
async function f() {
return 1;
}
ํจ์ ์์ async
๋จ์ด๋ ํ๊ฐ์ง ๋ป์ ์ง๋๋ค: ์ด ํจ์๋ ํญ์ promise๋ฅผ ๋ฆฌํดํฉ๋๋ค. ๋ค๋ฅธ ๊ฐ๋ค์ ์๋์ ์ผ๋ก resolve๋ promise๋ก ๊ฐ์ธ์ง๋๋ค.
์๋ฅผ ๋ค์ด, ์ด ํจ์๋ ๊ฒฐ๊ณผ๊ฐ 1์ธ resolve๋ promise๋ฅผ ๋ฐํํฉ๋๋ค.
async function f() {
return 1;
}
f().then(alert); // 1
์ฐ๋ฆฌ๋ ์๋ฌต์ ์ผ๋ก promise๋ฅผ ๋ฆฌํดํฉ๋๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
๊ทธ๋์ async
๋ ํจ์๊ฐ promise๋ฅผ ๋ฆฌํด ํ๋ ๊ฒ์ ๋ณด์ฅํ๊ณ , promise๊ฐ ์๋ ๊ฐ์ ํฌ์ฅํฉ๋๋ค. ๋งค์ฐ ๊ฐ๋จํ์ง ์์ต๋๊น? ์ด๊ฒ ๋์ด ์๋๋๋ค. await
์ ์ค์ง async
ํจ์ ์์์ ๋์ํฉ๋๋ค. ์ด๊ฒ์ ๋งค์ฐ ์ฟจํฉ๋๋ค.
Await
๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
// works only inside async functions
let value = await promise;
await
ํค์๋๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ promise๊ฐ ์
ํ
๋๊ณ ๊ทธ ๊ฒฐ๊ณผ ๊ฐ์ด ๋ฆฌํด๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
์ฌ๊ธฐ 1์ด ํ์ resolve๊ฐ ๋๋ promise ์์ ๊ฐ ์์ต๋๋ค.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("done!"), 1000)
});
let result = await promise; // wait till the promise resolves (*)
alert(result); // "done!"
}
f();
์ด ํจ์ ์คํ์ (*) ํ์ ํด๋ ๊ณณ์์ ์ ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ๊ทธ๋ฆฌ๊ณค promise๊ฐ ํด๊ฒฐ ๋์์๋ ๋ค์ ์ฌ๊ฐ ํฉ๋๋ค. ๊ทธ๋์ ์ ์ฝ๋์์ 1์ด ๋ค์ "done!" ์ด๋ผ๋ ๋ฉ์ธ์ง๋ฅผ ๋ณด๊ฒ ๋ฉ๋๋ค.
๊ฐ์กฐํฉ์๋ค: await
์ ๋ฌธ์ ๊ทธ๋๋ก promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋ง๋ญ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ฉด ๊ณ์ ์งํ์ด ๋ฉ๋๋ค. ์ด ์์
์ CPU ๋น์ฉ(๋ญ๋น)์ด ๋ค์ง ์์ต๋๋ค. ์๋ํ๋ฉด ์์ง์ ๊ทธ ๋์์ ๋ค๋ฅธ ์์
์ ํ ์ ์์ต๋๋ค. : ๋ค๋ฅธ ์คํฌ๋ฆฝํธ๋ ๋ค๋ฅธ ์ด๋ฒคํธ๋ฅผ ๋ค๋ฃฐ ์ ์์ต๋๋ค.
์ด๊ฒ์ promise๋ฅผ ์ป๊ธฐ์ promise.then
๋ณด๋ค ๋งค์ฐ ์ฐ์ํ ๋ฌธ๋ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฝ๊ณ ์ฐ๊ณ ๊ฐ ์ฝ์ต๋๋ค.
await
in regular functions
Canโt use ๋ง์ฝ await
์ ๋๊ธฐ์ ํจ์์์ ์ฌ์ฉํ๋ค๋ฉด ๋ฌธ๋ฒ ์๋ฌ๊ฐ ๋ ๊ฒ ์
๋๋ค.
function f() {
let promise = Promise.resolve(1);
let result = await promise; // Syntax error
}
ํจ์ ์์ async
๋ฅผ ๋ถ์ด์ง ์์๋ค๋ฉด ์๋ฌ๋ฅผ ๋ง์ฃผํ ๊ฒ์
๋๋ค. ๋ค์ ๋งํ์ง๋ง await
์ ์ค์ง async
ํจ์ ์์์ ์๋ ๋ฉ๋๋ค.
Promises chaining ์ฑํฐ์์ ์ผ๋ showAvarar()
๋ฅผ ๊ฐ์ ธ์ต์๋ค. ๊ทธ๋ฆฌ๊ณ async/await
์ ์ฌ์ฉํด์ ๋ค์ ์์ฑํด ๋ด
์๋ค.
- ์ฐ๋ฆฌ๋
.then
ํธ์ถ์await
์ผ๋ก ๋ฐ๊ฟ ํ์๊ฐ ์์ต๋๋ค. - ๋ํ ์ฐ๋ฆฌ๋ ์ด ์์
์ ์ํํ๊ธฐ ์ํด
async
ํจ์๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค.
async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
๋งค์ฐ ์ฝ๊ธฐ ์ฌ์์ง์ง ์์์ต๋๊น? ์ด์ ๋ณด๋ค ํจ์ฌ ๋์์ก์ต๋๋ค.
await
wonโt work in the top-level code
await
์ ์ฒ์ ์ฐ๋ ์ฌ๋๋ค์ ๋ค์๊ณผ ๊ฐ์ ์ฌ์ค์ ์์ด๋ฒ๋ฆด ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฝ๋์ ์ต์๋จ์ await
์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ ์๋ํ์ง ์์ต๋๋ค.
// syntax error in top-level code
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
์ฐ๋ฆฌ๋ ๋น๋๊ธฐ ํจ์๋ก ๊ฐ์ธ์ ํ ์ ์์ต๋๋ค.
(async () => {
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
...
})();
await
accepts โthenablesโ
promise.then
์ฒ๋ผ, await
๋ then ๋ฉ์๋๊ฐ ์๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ์์ด๋์ด๋ ์๋ํํฐ ๊ฐ์ฒด๊ฐ ๋ง์ฝ์ promise๊ฐ ์๋์ง๋ง promise ์ฒ๋ผ ์์ง์ผ์ ์๋: ๋ง์ฝ .then
์ ์ง์ํ๋ ๊ฐ์ฒด๋ผ๋ฉด ์ถฉ๋ถํ await
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ ๋ฐ๋ชจ๋ Thenable
ํด๋์ค์ await
์ด ์ด ์ธ์คํด์ค์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve);
// resolve with this.num*2 after 1000ms
setTimeout(() => resolve(this.num * 2), 1000); // (*)
}
};
async function f() {
// waits for 1 second, then result becomes 2
let result = await new Thenable(1);
alert(result);
}
๋ง์ฝ์ await
์ด .then
์ ๊ฐ๋ promise ๊ฐ์ฒด๊ฐ ์๋๊ฒฝ์ฐ ๊ทธ๊ฒ์ ๋ค์ดํฐ๋ธ ํจ์ resolve
, reject
๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ ๊ณต๋ฐ์ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ await
์ ๊ทธ์ค ํ๋๊ฐ ํธ์ถ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
Async class method
๋น๋๊ธฐ ํด๋์ค ๋ฉ์๋๋ฅผ ์ ์ธํ๊ธฐ ์ํด์๋ ๋จ์ง async
๋ง ํจ์ ์์ ๋ถ์ฌ์ฃผ๋ฉด ๋ฉ๋๋ค.
class Waiter {
async wait() {
return await Promise.resolve(1);
}
}
new Waiter()
.wait()
.then(alert); // 1
์ด๊ฒ์ ์๋ฏธ๋ ๋๊ฐ์ต๋๋ค. ๋ฐํ๋ฐ๋ ๊ฐ์ด promise์ด๊ณ await
์ ์ฌ์ฉํ ์ ์๋ค๋ ๋ณด์ฅ์ ํ๋ ๊ฒ์
๋๋ค.
Error handling
๋ง์ฝ promise ๊ฐ ํ๋ฒํ๊ฒ ๊ท๊ฒฐ์ด ๋์๋ค๋ฉด, await promise
๋ ๊ฐ์ ๋ฆฌํด ํ ๊ฒ์
๋๋ค. ํ์ง๋ง ๊ฑฐ์ ์ ์ผ์ด์ค์์๋ error๋ฅผ ๋์ง ๊ฒ์
๋๋ค. ๋ง์ฝ ํด๋น ๋ผ์ธ์ throw
๋ฌธ์ ๋ง๋๊ฒ ๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น
async function f() {
await Promise.reject(new Error("Whoops!"));
}
์ด๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
async function f() {
throw new Error("Whoops!");
}
์ค์ ์ํฉ์์ promise๋ ์๋ง reject ํ๊ธฐ์ ์ ๋ช๋ถ์ ์๊ฐ์ ๋ณด๋ผ ๊ฒ์
๋๋ค. ์ด ๊ฒฝ์ฐ await
์ด ์๋ฌ๋ฅผ ๋์ง๊ธฐ ๊น์ง delay ๊ฐ ์์ ๊ฑด๋ฐ์.
์ฐ๋ฆฌ๋ ์ด๋ ์๋ฌ๋ฅผ try...catch
๋ฌธ์ผ๋ก ์ก์๋ผ ์ ์์ต๋๋ค.
async function f() {
try {
let response = await fetch('http://no-such-url');
} catch(err) {
alert(err); // TypeError: failed to fetch
}
}
f();
์๋ฌ์ ๊ฒฝ์ฐ catch ๋ธ๋ญ์ผ๋ก ๋์ด๊ฐ๊ฒ ๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ํ ์ฌ๋ฌ์ค์ ๊ฐ์ธ ์ค ์๋ ์์ต๋๋ค.
async function f() {
try {
let response = await fetch('/no-user-here');
let user = await response.json();
} catch(err) {
// catches errors both in fetch and response.json
alert(err);
}
}
f();
๋ง์ฝ try...catch
๋ฌธ์ ๊ฐ์ง์ง ์๋๋ค๋ฉด f()๋ฅผ ํธ์ถํด ์์ฑํ promise๋ reject ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ฉด ์ฐ๋ฆฌ๋ .catch
์์ ๊ทธ๊ฒ์ ๋ค๋ฃฐ ์ ์์ต๋๋ค.
async function f() {
let response = await fetch('http://no-such-url');
}
// f() becomes a rejected promise
f().catch(alert); // TypeError: failed to fetch // (*)
๋ง์ฝ .catch
๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์์ด๋ฒ๋ ธ๋ค๋ฉด ์ด promise์ ์๋ฌ๋ฅผ ํธ๋ค๋ง ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ Error handling with promises ์ด ์ฑํฐ์์ ์ค๋ช
ํ ์ ์ญ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํด์ ๋ช๋ช ์๋ฌ๋ฅผ ์ก์๋ผ ์ ์์ต๋๋ค.
async/await
and promise.then/catch
์ฐ๋ฆฌ๊ฐ async/await
์ ์ฌ์ฉํ ๋, .then
์ด ๊ฑฐ์ ํ์๊ฐ ์๋ค, ์๋ํ๋ฉด await
๋ ์ฐ๋ฆฌ๋ฅผ ์ํด ๊ธฐ๋ค๋ ค์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ๋๊ฒ .catch
๋์ ์ try..catch
๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ๋ฐฉ๋ฒ์ ํญ์ ๊ทธ๋ ์ง ์์ ์ ์์ง๋ง ๋๊ฒ ํธ๋ฆฌํฉ๋๋ค.
ํ์ง๋ง ์ฝ๋ ์ต์์์์ async
ํจ์ ๋ฐ์์ ์ฌ์ฉํ ๋ ์ฐ๋ฆฌ๋ ๋ฌธ๋ฒ์ ์ผ๋ก await
์ ์ฌ์ฉํ ์๊ฐ ์์ต๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ์ต์ข
๊ฒฐ๊ณผ ๋๋ ์๋ฌ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด .then/catch
๋ฌธ์ ์ฐ์ตํด๋์ด์ผ ํฉ๋๋ค.
์ ์์ ์ (*) ๋ฌธ์์ ๋ณด๋ ๊ฒ๊ณผ ๊ฐ์ด์.
async/await
works well with Promise.all
์ฐ๋ฆฌ๊ฐ ์ฌ๋ฌ promise๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํ ๋, ์ฐ๋ฆฌ๋ ์ด๊ฒ๋ค์ Promise.all
๊ณผ await
๋ก ๊ฐ์ ์ ์์ต๋๋ค.
// wait for the array of results
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);
์๋ฌ๊ฐ ๋ฐ์๋ฌ์ ๊ฒฝ์ฐ ์คํจ๊ฐ Promise.all
๋ก ์ ํ๊ฐ ๋ฉ๋๋ค. ๊ทธ๋์ ๋ฐ์๋๋ ์์ธ๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ์ try...catch
๋ก ๊ฐ์ธ ์ก์๋
๋๋ค.
Summary
ํจ์ ์ ์ async
ํค์๋๋ฅผ ์ ๋๊ฒ์ ๋ค์ ๋๊ฐ์ง ํจ๊ณผ๋ฅผ ๊ฐ๋๋ค.
- ํญ์ promise๋ฅผ ๋ฐํํ๋ค.
- ์์ชฝ์
await
๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
promise ์ ์ await
ํค์๋๋ฅผ ๋ค๋ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ promise ๊ฐ ํด๊ฒฐ๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋ง๋ ๋ค. ๊ทธ ํ์
- ๋ง์ฝ ์๋ฌ๊ฐ ๋ฐ์ํด ์์ธ๊ฐ ์์ฑ๋ ์ ์๋ค. ๋ง์น
throw error
๋ฅผ ํธ์ถํ๋ ๊ฒ๊ณผ ๊ฐ์ด - ๋ฐ๋ฉด์ ๊ฐ์ด ๋ฆฌํด ๋ ์ ์๋ค.
์ด๋ค์ ํจ๊ป ์ฝ๊ณ ์ธ ์์๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ์ํ ํ๋ฅญํ ํ๋ ์ ์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
async / await๋ฅผ ์ฌ์ฉํ๋ฉด promise.then / catch
๋ฅผ ์์ฑํ ํ์๊ฐ ๊ฑฐ์ ์์ง๋ง promise์ ๊ธฐ๋ฐ์ผ๋กํ๋ค๋ ๊ฒ์ ์์ง ๋ง์์ผํฉ๋๋ค. ๋๋ก๋ (์ : ๊ฐ์ฅ ๋ฐ๊นฅ ์ชฝ ๋ฒ์์์) ์ด๋ฌํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ผํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ํ Promise.all ์ ๋ง์ ์์
์ ๋์์ ๊ธฐ๋ค๋ฆด ์์๋ ์ข์ ๋ฐฉ๋ฒ์
๋๋ค.