Promise
- : Promise is a JavaScript object for asynchronous operation.
- ๋น๋๊ธฐ๋ฅผ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ Object
๋คํธ์ํฌ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ฑฐ๋, ํ์ผ์์ ํฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ๊ณผ์ ์ ์๊ฐ์ด ๊ฝค ๊ฑธ๋ฆฐ๋ค
์ด๋ฐ ์ผ์ ๋๊ธฐ์ , synchronous๋ก ์ฒ๋ฆฌํ๋ฉด ํ์ผ์ ์ฝ์ด์ค๊ณ , ๋คํธ์ํฌ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๋์ ๋ค์ ๋์์ ์ํ ๋ชปํจ.
๋น๋๊ธฐ์ ์ธ ๊ฒ์ ์ํํ ๋, callback ํจ์ ๋์ ์ ์ ์ฉํ๊ฒ ์ธ ์ ์๋ค!
์ ํด์ง ์ฅ์๊ฐ์ ๊ธฐ๋ฅ์ ์ํํ๊ณ ๋์, ์ ์์ ์ธ ๊ธฐ๋ฅ์ด ์ํ๋๋ค๋ฉด ์ฑ๊ณต ๋ฉ์์ง์ ์ฒ๋ฆฌ๋ ๊ฒฐ๊ณผ๊ฐ์ ์ ๋ฌ.
๊ธฐ๋ฅ ์ํ์ค์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์๋ฌ๋ฅผ ์ ๋ฌํ๋ค.
- ์์ ์์ง ์คํํ์ง ์์ ๊ฐ์, ์ด๋ฉ์ผ์ ์ ๋ ฅํด์ ๋ฏธ๋ฆฌ ๋ฑ๋กํ๋ฉด ๊ฐ์๊ฐ ์คํ๋์ ๋ ๋ฉ์ผ์ ๋ณด๋ด์ค.
A์ ๊ฒฝ์ฐ
- A๊ฐ (์์ฑ๋)promise์ ๋ฑ๋ก
- ์๊ฐ์ด ์ง๋ ํ ์ฝ์ค๊ฐ ์คํ๋๋ฉด ๋ฉ์ผ์ ๋ฐ์(promise๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๊ฐ์ ์ ๋ฌํจ)
B์ ๊ฒฝ์ฐ
- B๊ฐ (์ด๋ฏธ ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋)promise์ ๋ฑ๋ก
- ์ด๋ฏธ ์คํ๋์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๋ฉ์ผ์ ๋ฐ์
โญ๏ธ ๊ณต๋ถ ํฌ์ธํธ!
- state
- Promise๊ฐ ๋ฌด๊ฑฐ์ด operation์ ์ํํ๊ณ ์๋ ์ค์ธ์ง
- ์๋๋ฉด ๊ธฐ๋ฅ์ํ์ด ๋๋์ ์ฑ๊ณต/์คํจํ๋์ง
- producer / consumer์ ์ฐจ์ด์
- ์ฐ๋ฆฌ๊ฐ ์ํ๋ producer๋ฅผ producing, ์ ๊ณตํ๋ ์ฌ๋๊ณผ
- ์ ๊ณต๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ์ฌ๋, ํ์๋ก ํ๋ ์ฌ๋ consumer
1-1. state
โญ๏ธ pending => fulfilled or rejected โญ๏ธ
(์ฒ๋ฆฌ์ค => ์ฑ๊ณต or ์คํจ)
-
- pending
- promise๊ฐ ๋ง๋ค์ด์ ธ์ ์ฐ๋ฆฌ๊ฐ ์ง์ ํ operation์ด ์ฌ์ฉ์ค์ผ ๋
-
- fulfilled
- operation์ ์ฑ๊ณต์ ์ผ๋ก ๋ค ๋๋์ ๋
-
- rejected
- ํ์ผ์ ์ฐพ์ ์ ์๊ฑฐ๋, ๋คํธ์ํฌ์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋
1-2. producer vs consumer
-
- producer
- ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ธฐ๋ฅ์ ์ํํด์ ํด๋นํ๋ data๋ฅผ ๋ง๋ค์ด๋ด๋, promise์ object
-
- consumer
- ์ฐ๋ฆฌ๊ฐ ์ํ๋ data๋ฅผ ์๋นํ๋, promise์ object
1. producer
: when new promise is created, the excutor runs automatically.
- promise๋ฅผ ๋ง๋๋ ์๊ฐ,์ ๋ฌํ ์ฝ๋ฐฑํจ์ excutor๊ฐ ๋ฐ๋ก ์คํ๋๋ค!
const promise = new Promise((resolve, reject) => {
// doing some heavy work(network, read files)
console.log("doing something...");
setTimeout(() => {
resolve("ellie");
reject(new Error("no network"));
// ์ฑ๊ณต์ ์ผ๋ก ๋คํธ์ํฌ์์ ๋ฐ์์จ, ํ์ผ์์ ์ฝ์ด์จ, ์ด๊ฒ๋ค์ ๊ฐ๊ณตํ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ฐฑํจ์ resolve๋ฅผ ํตํด์ ์ ๋ฌ
}, 2000);
});
// executor๋ผ๋ ์ฝ๋ฐฑํจ์๋ฅผ ์ ๋ฌํด์ผํจ. ๊ทธ ์ฝ๋ฐฑํจ์๋ ๋ ๋ค๋ฅธ ๋๊ฐ์ง์ ์ฝ๋ฐฑํจ์๋ฅผ ๋ฐ๋๋ค
- => ๋ง์ฝ ์ด promise์์ ๋คํธ์ํฌ ํต์ ์ ํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค๋ฉด, promise๊ฐ ๋ง๋ค์ด์ง๋ ์๊ฐ! ๋คํธ์ํฌ ํต์ ์ ์ํํ๊ฒ ๋๋ค
โญ๏ธ ์ฌ์ฉ์๊ฐ ์๊ตฌํ์ ๋์๋ง(๋ฒํผํด๋ฆญ) ๋คํธ์ํฌ ํต์ ์ ํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ ๊ฑธ ๊ผญ ๊ธฐ์ตํ ๊ฒ!
2. consumers : then, catch, finally
- then : ๊ฐ์ด ์ ์์ ์ผ๋ก ์ํ์ด ๋๋ค๋ฉด!
- catch : ๊ฐ์ด ์ ์์ ์ผ๋ก ์ํ์ด ๋์ง ์์๋ค๋ฉด!
- finally : ์ฑ๊ณตํ๋ ์คํจํ๋ ์๊ด์์ด ๋ฌด์กฐ๊ฑด ๋ง์ง๋ง์ ํธ์ถ
promise
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
})
.finally(() => console.log("finally"));
.then์ ๋๊ฐ์ promise๋ฅผ ๋ค์ ํธ์ถํ ์ ์๋ค. ๊ทธ๋์ ์ฐ๊ฒฐํด์ ์ธ ์ ์๋ ๊ฒ.
(array-api์์ ๋๊ฐ์ ๋ฐฐ์ด์ ๋ฆฌํดํ๋ map์ผ๋ก ์ฒด์ด๋ํ๋ ๊ฒ์ฒ๋ผ)
์ฑ๊ณตํ๋ค๋ฉด ๊ทธ ๊ฐ์ ๋ฐ์์์, ์ํ๋ ๊ธฐ๋ฅ์ ์ํํด์ฃผ๋ ์ฝ๋ฐฑํจ์๋ฅผ ์์ฑ
3. Promise chaining promise ์ฐ๊ฒฐํ๊ธฐ
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
fetchNumber
.then((num) => num * 2)
.then((num) => num * 3)
.then((num) => { //๋ค๋ฅธ ์๋ฒ์ ๋ณด๋ด์ ๋ค๋ฅธ ์ซ์๋ก ๋ณํ๋ ๊ฐ์ ๊ฐ์ ธ์จ๋ค
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000);
});
})
.then((num) => console.log(num));
4. Error Handling
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve("๐"), 1000);
});
const getEgg = (hen) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => ๐ฅ`), 1000);
setTimeout(() => reject(new Error(`error! ${hen} => ๐ฅ`)), 1000);
});
const cook = (egg) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => ๐ณ`), 1000);
});
getHen()
.then((hen) => getEgg(hen))
.then((egg) => cook(egg))
.then((meal) => console.log(meal));
์ฝ๋ฐฑํจ์๋ฅผ ์ ๋ฌํ ๋, ๋ฐ์์ค๋ value๋ฅผ ๋ค๋ฅธํจ์๋ก ๋ฐ๋ก ํธ์ถํ๋ ๊ฒฝ์ฐ์๋, ์๋์ฒ๋ผ ์ถ์ฝํ ์ ์๋ค
getHen() //
.then(getEgg)
.then(cook)
.then(console.log);
- then์์ ๋ฐ์์ค๋ value๋ฅผ ๋ฐ๋ก getEggํจ์์ ๋ฃ์ด์ ํธ์ถ
- then์์ ๋ฐ์์ค๋ value๋ฅผ ๋ฐ๋ก cookํจ์์ ๋ฃ์ด์ ํธ์ถ
getHen() //
.then(getEgg)
.catch((error) => {
return "๐";
})
.then(cook)
.then(console.log)
.catch(console.log);
์ค๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ฒจ๋ ์ ์ฒด์ ์ธ promise ์ฒด์ธ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋นต!๊พธ! ์ฒ๋ฆฌ๋ฅผ ํด์ค๋ค
ํน์ ๋ถ๋ถ์์ ๋ฐ์ํ๋ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ถ์ ๋,
๋ฐ๋ก ๊ทธ ๋ค์์ catch๋ฅผ ์์ฑํด์ ๋ฐ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐ.๐ฅ
5. ๐ฉ => โจโจโจโจ (์ฝ๋ฐฑ์ง์ฅ ๊ฐ์ ํ๊ธฐ)
(before) callback์ผ๋ก๋ง ์์ฑํ ์ฝ๋ ๐ฉ
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === "ellie" && password === "dream") ||
(id === "coder" && password === "academy")
) {
onSuccess(id);
} else {
onError(new Error("not found"));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === "ellie") {
onSuccess({ name: "ellie", role: "admin" });
} else {
onError(new Error("not access"));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage.loginUser(
id,
password,
(user) => {
userStorage.getRoles(
user,
(userWithRole) => {
alert(
`Hello, ${userWithRole.name}, you have a ${userWithRole.role} role`
);
},
(error) => {
onsole.log("error");
}
);
},
(error) => console.log("error")
);
(after) promise๋ก ๋ณ๊ฒฝํ ์ฝ๋! โจ
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
// promise์์์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์ํํ๋ ํจ์๋ฅผ ๋ฃ๊ณ
setTimeout(() => {
if (
(id === "ellie" && password === "dream") ||
(id === "coder" && password === "academy")
) {
resolve(id);
} else {
reject(new Error("not found"));
}
}, 2000);
});
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === "ellie") {
resolve({ name: "ellie", role: "admin" });
} else {
reject(new Error("not access"));
}
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage
.loginUser(id, password) //loginUser๋ฅผ ํธ์ถํค์ id์ psw๋ฅผ ์๋ ค์ค
.then((user) => userStorage.getRoles(user)) // ์๋ ค์ฃผ๋๋ฐ ์ฑ๊ณตํ๋ฉด
.then((user) => alert(`Hello, ${user.name}, you have a ${user.role} role`)) //์ถ๋ ฅ
.catch(console.log);