์๋ฐ์คํฌ๋ฆฝํธ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ํ๋์ ํจํด์ผ๋ก ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฌ์ฉํ๋ค. ํ์ง๋ง ์ฝ๋ฐฑ ํจํด์ ์ฝ๋ฐฑ ํฌ๋ก ์ธํด ๊ฐ๋
์ฑ์ด ๋์๊ณ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ค ๋ฐ์ํ ์๋ฌ์ ์ฒ๋ฆฌ๊ฐ ๊ณค๋ํ๋ฉฐ ์ฌ๋ฌ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ฒ์ ์ฒ๋ฆฌํ๋ ๋ฐ๋ ํ๊ณ๊ฐ ์๋ค.
ES6์์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋ ๋ค๋ฅธ ํจํด์ผ๋ก ํ๋ก๋ฏธ์ค๋ฅผ ๋์
ํ๋ค. ํ๋ก๋ฏธ์ค๋ ์ ํต์ ์ธ ์ฝ๋ฐฑ ํจํด์ด ๊ฐ์ง ๋จ์ ์ ๋ณด์ํ๋ฉฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ ์ ๋ช
ํํ๊ฒ ํํํ ์ ์๋ค๋ ์ฅ์
์ด ์๋ค.
//GET ์์ฒญ์ ์ํ ๋น๋๊ธฐ ํจ์
const get = url => {
const xhr = new XHMLHttpRequest();
xhr.open('GET', url_;
xhr.send();
xhr.onload =()=>{
if(xhr.status ===200){
console.log(JSON.parse(xhr.response));
}else{
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
// id๊ฐ 1์ธ post๋ฅผ ์ทจ๋
get('https://jsonplaceholder.typicode.com/posts/1';
/*
{
"userId": 1,
"id": 1,
"title" "sunt aut dssfd...",
"body" "sfsdsafd aa sdffdsd..."
}
*/
์ ์์ ์ get ํจ์๋ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๋ฅผ ์ฝ์์ ์ถ๋ ฅํ๋ค. get ํจ์๊ฐ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ฒ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ๋ ๊น?
get ํจ์๋ ๋น๋๊ธฐ ํจ์๋ค. ๋น๋๊ธฐ ํจ์๋ ํจ์ ๋ด๋ถ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ ์ฝ๋๋ฅผ ํฌํจํ ํจ์๋ฅผ ๋งํ๋ค. ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ํจ์ ๋ด๋ถ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ ์ฝ๋๊ฐ ์๋ฃ๋์ง ์์๋ค ํด๋ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ฆ์ ์ข
๋ฃ๋๋ค. ์ฆ, ๋น๋๊ธฐ ํจ์ ๋ด๋ถ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ ์ฝ๋๋ ๋น๋๊ธฐ ํจ์๊ฐ ์ข
๋ฃ๋ ์ดํ์ ์๋ฃ๋๋ค. ๋ฐ๋ผ์ ๋น๋๊ธฐ ํจ์ ๋ด๋ถ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ ์ฝ๋์์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ธ๋ถ๋ก ๋ฐํํ๊ฑฐ๋ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ๋ฉด ๊ธฐ๋ํ ๋๋ก ๋์ํ์ง ์๋๋ค.
let g = 0;
// ๋น๋๊ธฐ ํจ์์ธ setTimeout ํจ์๋ ์ฝ๋ฐฑ ํจ์์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ธ๋ถ๋ก ๋ฐํํ๊ฑฐ๋ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ์ง ๋ชปํ๋ค.
setTimeout(() => {g = 100;}, 0);
console.log(g); // 0
GET ์์ฒญ์ ์ ์กํ๊ณ ์๋ฒ์ ์๋ต์ ์ ๋ฌ๋ฐ๋ get ํจ์๋ ๋น๋๊ธฐ ํจ์๋ค. get ํจ์๊ฐ ๋น๋๊ธฐ ํจ์์ธ ์ด์ ๋ get ํจ์ ๋ด๋ถ์ onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋น๋๊ธฐ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ด๋ค. get ํจ์๋ฅผ ํธ์ถํ๋ฉด GET ์์ฒญ์ ์ ์กํ๊ณ onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํ ๋ค์ undefined๋ฅผ ๋ฐํํ๊ณ ์ฆ์ ์ข ๋ฃ๋๋ค. ์ฆ, ๋น๋๊ธฐ ํจ์์ธ get ํจ์ ๋ด๋ถ์ onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ get ํจ์๊ฐ ์ข ๋ฃ๋ ์ดํ์ ์คํ๋๋ค. ๋ฐ๋ผ์ get ํจ์์ onload ์ด๋ฒคํธ ํธ๋ค๋ฌ์์ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ฑฐ๋ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ๋ฉด ๊ธฐ๋ํ ๋๋ก ๋์ํ์ง ์๋๋ค.
get ํจ์๊ฐ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋๋ก ์์ ํด ๋ณด์.
//GET ์์ฒญ์ ์ํ ๋น๋๊ธฐ ํจ์
const get = url => {
const xhr = new XHMLHttpRequest();
xhr.open('GET', url);
xhr.send();
xhr.onload =()=>{
if(xhr.status ===200){
// 1. ์๋ฒ์ ์๋ต์ ๋ฐํํ๋ค.
return JSON.parse(xhr.response);
}else{
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
// id๊ฐ 1์ธ post๋ฅผ ์ทจ๋
const response= get('https://jsonplaceholder.typicode.com/posts/1';
console.log(response); //undefined
get ํจ์๊ฐ ํธ์ถ๋๋ฉด XMLHttpRequest ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , HTTP ์์ฒญ์ ์ด๊ธฐํํ ํ, HTTP ์์ฒญ์ ์ ์กํ๋ค. ๊ทธ๋ฆฌ๊ณ xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ๋กํผํฐ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฐ์ธ๋ฉํ๊ณ ์ข ๋ฃํ๋ค. ์ด๋ get ํจ์์ ๋ช ์์ ์ธ ๋ฐํ๋ฌธ์ด ์์ผ๋ฏ๋ก get ํจ์๋ undefined๋ฅผ ๋ฐํํ๋ค(2)
xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉํ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ฐํ๋ฌธ(1)์ get ํจ์์ ๋ฐํ๋ฌธ์ด ์๋๋ค. ํจ์์ ๋ฐํ๊ฐ์ ๋ช ์์ ์ผ๋ก ํธ์ถํ ๋ค์์ ์บ์นํ ์ ์์ผ๋ฏ๋ก onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ get ํจ์๊ฐ ํธ์ถํ ์ ์๋ค๋ฉด ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ฐํ๊ฐ์ get ํจ์๊ฐ ์บ์นํ์ฌ ๋ค์ ๋ฐํํ ์๋ ์๊ฒ ์ง๋ง onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ get ํจ์๊ฐ ํธ์ถํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ด ์๋ ์๋ค. ๋ฐ๋ผ์ onload ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ฐํ๊ฐ์ ์บ์นํ ์ ์๋ค.
<!DOCTYPE html>
<html>
<body>
<input type="text>
<script>
document.querySelector('input').oninput = function () {
console.log(this.value);
// ์ด๋ฒคํธ ํธ๋ค๋ฌ์์์ ๋ฐํ์ ์๋ฏธ๊ฐ ์๋ค.
return this.value;
};
</script>
</body>
</html>
๊ทธ๋ ๋ค๋ฉด 1์์ ์๋ฒ์ ์๋ต์ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ๋ฉด ์ด๋จ๊น?
let todos;
//GET ์์ฒญ์ ์ํ ๋น๋๊ธฐ ํจ์
const get = url => {
const xhr = new XHMLHttpRequest();
xhr.open('GET', url_;
xhr.send();
xhr.onload =()=>{
if(xhr.status ===200){
// 1. ์๋ฒ์ ์๋ต์ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ๋ค.
todos = JSON.parse(xhr.response);
}else{
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
// id๊ฐ 1์ธ post๋ฅผ ์ทจ๋get('https://jsonplaceholder.typicode.com/posts/1';
console.log(todos); //undefined
xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉํ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ์ธ์ ๋ 2์ console.log๊ฐ ์ข
๋ฃํ ์ดํ์ ํธ์ถํ๋ค. ๋ฐ๋ผ์ 2์ ์์ ์๋ ์์ง ์ ์ญ ๋ณ์ todos์ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๊ฐ ํ ๋น๋๊ธฐ ์ด์ ์ด๋ค. ๋ค์ ๋งํด. xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ์์ ์๋ฒ์ ์๋ต์ ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋น(1)ํ๋ฉด ์ฒ๋ฆฌ ์์๊ฐ ๋ณด์ฅ๋์ง ์๋๋ค.
๊ทธ ์ด์ ์ ๋ํด ์ดํด๋ณด์
๋น๋๊ธฐ ํจ์ get์ด ํธ์ถ๋๋ฉด ํจ์ ์ฝ๋๋ฅผ ํ๊ฐํ๋ ๊ณผ์ ์์ get ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋๊ณ ์คํ ์ปจํ ์คํธ ์คํ์ ํธ์๋๋ค. ์ดํ ํจ์ ์ฝ๋ ์คํ ๊ณผ์ ์์ xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ๋กํผํฐ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
get ํจ์๊ฐ ์ข ๋ฃํ๋ฉด get ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์์ ํ๋๊ณ , ๊ณง๋ฐ๋ก 2์ console.log๊ฐ ํธ์ถ๋๋ค. ์ด๋ console.log์ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋์ด ์คํ ์ปจํ ์คํธ ์คํ์ด ํธ์๋๋ค. ๋ง์ฝ console.log๊ฐ ํธ์ถ๋๊ธฐ ์ง์ ์ load ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ผ๋ xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉํ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ๊ฒฐ์ฝ console.log๋ณด๋ค ๋จผ์ ์คํ๋์ง ์๋๋ค.
์๋ฒ๋ก๋ถํฐ ์๋ต์ด ๋์ฐฉํ๋ฉด xhr ๊ฐ์ฒด์์ load ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค. ์ด๋ xhr.onload ํธ๋ค๋ฌ ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉํ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ฆ์ ์คํ๋๋ ๊ฒ์ด ์๋๋ค. xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ load ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์ผ๋จ ํ ์คํฌ ํ์ ์ ์ฅ๋์ด ๋๊ธฐํ๋ค๊ฐ, ์ฝ ์คํ์ด ๋น๋ฉด ์ด๋ฒคํธ ๋ฃจํ์ ์ํด ์ฝ ์คํ์ผ๋ก ํธ์๋์ด ์คํ๋๋ค. ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ํจ์์ด๋ฏ๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํ๊ฐ โ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์คํ ์ปจํ ์คํธ ์์ฑ โ ์ฝ ์คํ์ ํธ์ โ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์คํ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
๋ฐ๋ผ์ xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์คํ๋๋ ์์ ์๋ ์ฝ ์คํ์ด ๋น ์ํ์ฌ์ผ ํ๋ฏ๋ก 2์ console.log๋ ์ด๋ฏธ ์ข ๋ฃ๋ ์ดํ๋ค. ๋ง์ฝ get ํจ์ ์ดํ์ console.log๊ฐ 100๋ฒ ํธ์ถ๋๋ค ํด๋ xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ๋ชจ๋ console.log๊ฐ ์ข ๋ฃํ ์ดํ์ ์คํ๋๋ค. ์ฆ, xhr.onload ์ด๋ฒคํธ ํธ๋ค๋ฌ์์ ์์ ์ค์ฝํ์ ๋ณ์์ ์๋ฒ์ ์๋ต ๊ฒฐ๊ณผ๋ฅผ ํ ๋นํ๊ธฐ ์ด์ ์ console.log๊ฐ ๋จผ์ ํธ์ถ๋์ด undefined๊ฐ ์ถ๋ ฅ๋๋ค.
์ด์ฒ๋ผ ๋น๋๊ธฐ ํจ์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ธ๋ถ์ ๋ฐํํ ์ ์๊ณ , ์์ ์ค์ฝํ์ ๋ณ์์ ํ ๋นํ ์๋ ์๋ค. ๋ฐ๋ผ์ ๋น๋๊ธฐ ํจ์์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ(์๋ฒ์ ์๋ต ๋ฑ)์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ ๋น๋๊ธฐ ํจ์ ๋ด๋ถ์์ ์ํํด์ผ ํ๋ค. ์ด๋ ๋ฐ๋๊ธฐ ํจ์๋ฅผ ๋ฒ์ฉ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด ๋น๋๊ธฐ ํจ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค. ํ์์ ๋ฐ๋ผ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณตํ๋ฉด ํธ์ถ๋ ์ฝ๋ฐฑ ํจ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์คํจํ๋ฉด ํธ์ถ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํ ์ ์๋ค,
//GET ์์ฒญ์ ์ํ ๋น๋๊ธฐ ํจ์
const get = (url, successCallback, failureCallback) => {
const xhr = new XHMLHttpRequest();
xhr.open('GET', url_;
xhr.send();
xhr.onload =()=>{
if(xhr.status ===200){
// ์๋ฒ์ ์๋ต์ ์ฝ๋ฐฑ ํจ์์ ์ธ์๋ก ์ ๋ฌํ๋ฉด์ ํธ์ถํ์ฌ ์๋ต์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
successCallback(JSON.parse(xhr.response));
}else{
// ์๋ฌ ์ ๋ณด๋ฅผ ์ฝ๋ฐฑ ํจ์์ ์ธ์๋ก ์ ๋ฌํ๋ฉด์ ํธ์ถํ์ฌ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
failureCallback(xhr.status);
}
};
};
// id๊ฐ 1์ธ post๋ฅผ ์ทจ๋
// ์๋ฒ์ ์๋ต์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋น๋๊ธฐ ํจ์์ธ get์ ์ ๋ฌํด์ผ ํ๋ค.
get(
'https://jsonplaceholder.typicode.com/posts/1',
console.log,
console.error
);
์ด์ฒ๋ผ ์ฝ๋ฐฑ ํจ์๋ฅผ ํตํด ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ ๋น๋๊ธฐ ํจ์๊ฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ๋๋ค์ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํด์ผ ํ๋ค๋ฉด ์ฝ๋ฐฑ ํจ์ ํธ์ถ์ด ์ค์ฒฉ๋์ด ๋ณต์ก๋๊ฐ ๋์์ง๋ ํ์์ด ๋ฐ์ํ๋๋ฐ, ์ด๋ฅผ ์ฝ๋ฐฑ ํฌ์ด๋ผ ํ๋ค.
// GET ์์ฒญ์ ์ํ ๋น๋๊ธฐ ํจ์
const get = (url, callback) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
// ์๋ฒ์ ์๋ต์ ์ฝ๋ฐฑ ํจ์์ ์ ๋ฌํ๋ฉด์ ํธ์ถํ์ฌ ์๋ต์ ๋ํ ํ์ ์ฒ๋ฆฌ๋ฅผ ํ๋ค..
callback(JSON.parse(xhr.response));
} else {
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
const url = 'https://jsonplaceholder.typicode.com';
// id๊ฐ 1์ธ post์ userId๋ฅผ ์ทจ๋
get(`${url}/posts/1`, ({ userId }) => {
console.log(userId) ; // 1
// post์ userId๋ฅผ ์ฌ์ฉํ์ฌ user ์ ๋ณด๋ฅผ ์ทจ๋
get(`${url}/users/${userId}`, userInfo => {
console.log(userInfo); // {id: 1, name: "Leanne Graham", username: "bret", ...}
});
});
์ ์์ ๋ฅผ ๋ณด๋ฉด GET ์์ฒญ์ ํตํด ์๋ฒ๋ก๋ถํฐ ์๋ต(id๊ฐ 1์ธ post)์ ์ทจ๋ํ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋๋ค์ GET ์์ฒญ์ ํ๋ค. ์ฝ๋ฐฑ ํฌ์ ๊ฐ๋ ์ฑ์ ๋์๊ฒ ํ๋ฉฐ ์ค์๋ฅผ ์ ๋ฐํ๋ ์์ธ์ด ๋๋ค. ๋ค์์ ์ฝ๋ฐฑ ํฌ์ด ๋ฐ์ํ๋ ์ฌ๋ก๋ค.
get('/step1', a => {
get(`/step2/${a}`, b => {
get(`/step3/${b}`, c => {
get(`/step4/${c}`, d => {
console.log(d);
});
});
});
});
๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋ฐฑ ํจํด์ ๋ฌธ์ ์ ์ค์์ ๊ฐ์ฅ ์ฌ๊ฐํ ๊ฒ์ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๊ณค๋ํ๋ค๋ ๊ฒ์ด๋ค.
try {
setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
// ์๋ฌ๋ฅผ ์บ์นํ์ง ๋ชปํ๋ค
console.error('์บ์นํ ์๋ฌ', e);
}
๋น๋๊ธฐ ํจ์์ธ setTimeout์ด ํธ์ถ๋๋ฉด setTimeout ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋์ด ์ฝ ์คํ์ ํธ์๋์ด ์คํ๋๋ค. setTImeout์ ๋น๋๊ธฐ ํจ์์ด๋ฏ๋ก ์ฝ๋ฐฑ ํจ์๊ฐ ํธ์ถ๋๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ฆ์ ์ข ๋ฃ๋์ด ์ฝ ์คํ์์ ์ ๊ฑฐ๋๋ค. ์ดํ ํ์ด๋จธ๊ฐ ์๋ฃ๋๋ฉด setTimeout ํจ์์ ์ฝ๋ฐฑ ํจ์๋ ํ์คํฌ ํ๋ก ํธ์๋๊ณ ์ฝ ์คํ์ด ๋น์ด์ก์ ๋ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด ์ฝ ์คํ์ผ๋ก ํธ์๋์ด ์คํ๋๋ค.
setTimeout ํจ์์ ์ฝ๋ฐฑ ํจ์๊ฐ ์คํ๋ ๋ setTimeout ํจ์๋ ์ด๋ฏธ ์ฝ ์คํ์์ ์ ๊ฑฐ๋ ์ํ๋ค. ์ด๊ฒ์ setTImeout ํจ์์ ์ฝ๋ฐฑ ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ด setTimeout ํจ์๊ฐ ์๋๋ผ๋ ๊ฒ์ ์๋ฏธํ๋ค. setTimeout ํจ์์ ์ฝ๋ฐฑ ํจ์์ ํธ์ถ์๊ฐ setTimeout ํจ์๋ผ๋ฉด ์ฝ ์คํ์ ํ์ฌ ์คํ ์ค์ธ ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ๋ฐฑ ํจ์์ ์คํ ์ปจํ ์คํธ์ผ ๋ ํ์ฌ ์คํ ์ค์ธ ์คํ ์ปจํ ์คํธ์ ํ์ ์คํ ์ปจํ ์คํธ๊ฐ setTimeout ํจ์์ฌ์ผ ํ๋ค
์๋ฌ๋ ํธ์ถ์ ๋ฐฉํฅ์ผ๋ก ์ ํ๋๋ค ์ฆ, ์ฝ ์คํ์ ์๋ ๋ฐฉํฅ์ผ๋ก ์ ํ๋๋ค. ํ์ง๋ง ์์์ ์ดํด๋ณธ ๋ฐ์ ๊ฐ์ด setTimeout ํจ์์ ์ฝ๋ฐฑ ํจ์๊ฐ ๋ฐ์์ํจ ์๋ฌ๋ catch ๋ธ๋ก์์ ์บ์น๋์ง ์๋๋ค.
๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋ฐฑ ํจํด์ ์ฝ๋ฐฑ ํฌ์ด๋ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๊ณค๋ํ๋ค๋ ๋ฌธ์ ๊ฐ ์๋ค.๐ด
Promise ์์ฑ์ ํจ์๋ฅผ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ๋ฉด ํ๋ก๋ฏธ์ค๋ฅผ ์์ฑํ๋ค. ES6์์ ๋์
๋ Promise๋ ํธ์คํธ ๊ฐ์ฒด๊ฐ ์๋ ECMAScript ์ฌ์์ ์ ์๋ ํ์ค ๋นํธ์ธ ๊ฐ์ฒด๋ค.
Promise ์์ฑ์ ํจ์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ฐ ์ด ์ฝ๋ฐฑ ํจ์๋ resolve์ reject ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค.
// ํ๋ก๋ฏธ์ค ์์ฑ
const promise = new Promise((resolve, reject) => {
// Promise ํจ์์ ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค
if (/* ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ฑ๊ณต */) {
resolve('result');
}else{ /* ๋น๋๊ธฐ ์ฒ๋ฆฌ ์คํจ */
reject('failure reason');
}
});
Promise ์์ฑ์ ใ ๋ง์๊ฐ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค. ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณตํ๋ฉด ์ฝ๋ฐฑ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋ฐ์ resolve ํจ์๋ฅผ ํธ์ถํ๊ณ , ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์คํจํ๋ฉด reject ํจ์๋ฅผ ํธ์ถํ๋ค.
ํ๋ก๋ฏธ์ค๋ ๋ค์๊ณผ ๊ฐ์ด ํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ์งํ๋๊ณ ์๋์ง๋ฅผ ๋ํ๋ด๋ ์ํ์ ๋ณด๋ฅผ ๊ฐ๋๋ค.
ํ๋ก๋ฏธ์ค์ ์ํ ์ ๋ณด | ์๋ฏธ | ์ํ ๋ณ๊ฒฝ ์กฐ๊ฑด |
---|---|---|
pending | ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์์ง ์ํ๋์ง ์์ ์ํ | ํ๋ก๋ฏธ์ค๊ฐ ์์ฑ๋ ์งํ ๊ธฐ๋ถ ์ํ |
fulfilled | ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ํ๋ ์ํ(์ฑ๊ณต) | resolve ํจ์ ํธ์ถ |
rejected | ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ํ๋ ์ํ(์คํจ) | reject ํจ์ ํธ์ถ |
ํ๋ก๋ฏธ์ค์ ์ํ๋ resolve ๋๋ reject ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ๋ก ๊ฒฐ์ ๋๋ค.
fulfilled ๋๋ rejected ์ํ๋ฅผ settled ์ํ๋ผ๊ณ ํ๋ค. settled ์ํ๋ fulfilled ๋๋ rejected ์ํ์ ์๊ด์์ด pending์ด ์๋ ์ํ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ํ๋ ์ํ๋ฅผ ๋งํ๋ค.
ํ๋ก๋ฏธ์ค๋ pending ์ํ์์ fulfilled ๋๋ rejected ์ํ, ์ฆ settled ์ํ๋ก ๋ณํํ ์ ์๋ค. ํ์ง๋ง ์ผ๋จ settled ์ํ๊ฐ ๋๋ฉด ๋๋ ๋ค๋ฅธ ์ํ๋ก ๋ณํํ ์ ์๋ค.
ํ๋ก๋ฏธ์ค๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ํ์ ๋๋ถ์ด ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ ์ํ๋ก ๊ฐ๋๋ค.
// fulfilled๋ ํ๋ก๋ฏธ์ค
const fulfilled = new Promise(resolve => resolve(1));
๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณตํ๋ฉด ํ๋ก๋ฏธ์ค๋ pending ์ํ์์ fulfilled ์ํ๋ก ๋ณํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ธ 1์ ๊ฐ์ผ๋ก ๊ฐ๋๋ค.
// rejected๋ ํ๋ก๋ฏธ์ค
const rejected = new Promise((_, reject) => reject(new Error('error occurred')));
๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์คํจํ๋ฉด ํ๋ก๋ฏธ์ค๋ pending ์ํ์์ rejected ์ํ๋ก ๋ณํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ธ Error ๊ฐ์ฒด๋ฅผ ๊ฐ์ ๊ฐ๋๋ค. ์ฆ, ํ๋ก๋ฏธ์ค๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ํ์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด๋ค.
ํ๋ก๋ฏธ์ค์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ํ๊ฐ ๋ณํํ๋ฉด ์ด์ ๋ฐ๋ฅธ ํ์ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ๋ค. ํ๋ก๋ฏธ์ค๊ฐ fulfilled ์ํ๊ฐ ๋๋ฉด ํ๋ก๋ฏธ์ค์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ๋ฌด์ธ๊ฐ๋ฅผ ํด์ผ ํ๊ณ , ํ๋ก๋ฏธ์ค๊ฐ rejected ์ํ๊ฐ ๋๋ฉด ํ๋ก๋ฏธ์ค์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ๋ค. ์ด๋ฅผ ์ํด ํ๋ก๋ฏธ์ค๋ ํ์ ๋ฉ์๋ then, catch, finally๋ฅผ ์ ๊ณตํ๋ค.
ํ๋ก๋ฏธ์ค์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ํ๊ฐ ๋ณํํ๋ฉด ํ์ ์ฒ๋ฆฌ ๋ฉ์๋์ ์ธ์๋ก ์ ๋ฌํ ์ฝ๋ฐฑ ํจ์๊ฐ ์ ํ์ ์ผ๋ก ํธ์ถ๋๋ค. ์ด๋ ํ์ ์ฒ๋ฆฌ ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์์ ํ๋ก๋ฏธ์ค์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ์ธ์๋ก ์ ๋ฌ๋๋ค.
then ๋ฉ์๋๋ ๋ ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค.
์ฆ, ์ฒซ ๋ฒ์จฐ ์ฝ๋ฐฑ ํจ์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณตํ์ ๋ ํธ์ถ๋๋ ์ฑ๊ณต ์ฒ๋ฆฌ ์ฝ๋ฐฑ ํจ์์ด๋ฉฐ, ๋ ๋ฒ์งธ ์ฝ๋ฐฑ ํจ์๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์คํจํ์ ๋ ํธ์ถ๋๋ ์คํจ ์ฒ๋ฆฌ ์ฝ๋ฐฑ ํจ์๋ค.
// fulfilled
new Promise(resolve => resolve('fulfilled'))
.then(v => console.log(v), e=> console.error(e)); // fulfilled
// rejected
new Promise((_, reject) => reject(new Error('rejected')))
.then(v => console.log(v), e=> console.error(e)); // Error : rejected
then ๋ฉ์๋๋ ์ธ์ ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค. ๋ง์ฝ then ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์๊ฐ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ฉด ๊ทธ ํ๋ก๋ฏธ์ค๋ฅผ ๊ทธ๋๋ก ๋ฐํํ๊ณ , ์ฝ๋ฐฑ ํจ์๊ฐ ํ๋ก๋ฏธ์ค๊ฐ ์๋ ๊ฐ์ ๋ฐํํ๋ฉด ๊ทธ ๊ฐ์ ์๋ฌต์ ์ผ๋ก resolve ๋๋ rejectํ์ฌ ํ๋ก๋ฏธ์ค๋ฅผ ์์ฑํด ๋ฐํํ๋ค.
catch ๋ฉ์๋๋ ํ ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค. catch ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์๋ ํ๋ก๋ฏธ์ค๊ฐ rejected ์ํ์ธ ๊ฒฝ์ฐ๋ง ํธ์ถ๋๋ค.
// rejected
new Promise((_, reject) => reject(new Error('rejected')))
.catch(e => console.log(e)); // Error: rejectd
catch ๋ฉ์๋๋ then(undefined, onRejected)๊ณผ ๋์ผํ๊ฒ ๋์ํ๋ค. ๋ฐ๋ผ์ then ๋ฉ์๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ธ์ ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค.
finally ๋ฉ์๋๋ ํ ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค. finally ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์๋ ํ๋ก๋ฏธ์ค์ ์ฑ๊ณต๋๋ ์คํจ์ ์๊ด์์ด ๋ฌด์กฐ๊ฑด ํ ๋ฒ ํธ์ถ๋๋ค. finally ๋ฉ์๋๋ ํ๋ก๋ฏธ์ค์ ์ํ์ ์๊ด์์ด ๊ณตํต์ ์ผ๋ก ์ํํด์ผ ํ ์ฒ๋ฆฌ ๋ด์ฉ์ด ์์ ๋ ์ ์ฉํ๋ค. finally ๋ฉ์๋๋ then/catch ๋ฉ์๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ธ์ ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค.
new Promise(() => {})
.finally(() => console.log('finally')); // finally
๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋ฐฑ ํจํด์ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๊ณค๋ํ๋ค๋ ๋ฌธ์ ๊ฐ ์๋ค. ํ๋ก๋ฏธ์ค๋ ์๋ฌ๋ฅผ ๋ฌธ์ ์์ด ์ฒ๋ฆฌํ ์ ์๋ค.
๋น๋๊ธฐ ์ฒ๋ฆฌ์์ ๋ฐ์ํ ์๋ฌ๋ then ๋ฉ์๋์ ๋ ๋ฒ์งธ ์ฝ๋ฐฑ ํจ์๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
const wrongUrl = 'https://jsonplaceholder.typicode.com/xxx/1';
// ๋ถ์ ์ ํ URL์ด ์ง์ ๋์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
promiseGet(wrongurl).then(
res => console.log(res),
err => console.error(err)
); // Error: 404
catch๋ฅผ ์ฌ์ฉํด ์ฒ๋ฆฌํ ์๋ ์๋ค.
const wrongUrl = 'https://jsonplaceholder.typicode.com/xxx/1';
// ๋ถ์ ์ ํ URL์ด ์ง์ ๋์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
promiseGet(wrongUrl)
.then(res => console.log(res));
.catch(err => console.error(err)); // Error: 404
catch ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ด๋ถ์ ์ผ๋ก then(undefined, onRejected)์ ํธ์ถํ๋ค. ๋ฐ๋ผ์ ์ ์์ ๋ ๋ด๋ถ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ฒ๋ฆฌ๋๋ค.
const wrongUrl = 'https://jsonplaceholder.typicode.com/xxx/1';
// ๋ถ์ ์ ํ URL์ด ์ง์ ๋์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
promiseGet(wrongUrl)
.then(res => console.log(res))
.then(undefined, err => console.error(err)); // Error : 404
๋จ, then ๋ฉ์๋์ ๋ ๋ฒ์จฐ ์ฝ๋ฐฑ ํจ์๋ ์ฒซ ๋ฒ์งธ ์ฝ๋ฐฑ ํจ์์์ ๋ฐ์ํ ์๋ฌ๋ฅผ ์บ์นํ์ง ๋ชปํ๊ณ ์ฝ๋๊ฐ ๋ณต์กํด์ ธ์ ๊ฐ๋ ์ฑ์ด ์ข์ง ์๋ค.
catch ๋ฉ์๋๋ฅผ ๋ชจ๋ then ๋ฉ์๋๋ฅผ ํธ์ถํ ์ดํ์ ํธ์ถํ๋ฉด ๋น๋๊ธฐ ์ฒ๋ฆฌ์์ ๋ฐ์ํ ์๋ฌ๋ฟ๋ง ์๋๋ผ then ๋ฉ์๋ ๋ด๋ถ์์ ๋ฐ์ํ ์๋ฌ๊น์ง ๋ชจ๋ ์บ์นํ ์ ์๋ค.
๋ํ then ๋ฉ์๋์ ๋ ๋ฒ์จฐ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ๋ณด๋ค catch ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ๋ ์ฑ์ด ์ข๊ณ ๋ช ํํ๋ค. ๋ฐ๋ผ์ ์๋ฌ ์ฒ๋ฆฌ๋ then ๋ฉ์๋์์ ํ์ง ๋ง๊ณ catch ๋ฉ์๋์์ ํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
ํ๋ก๋ฏธ์ค๋ then, catch, finally ํ์ ์ฒ๋ฆฌ ๋ฉ์๋๋ฅผ ํตํด ์ฝ๋ฐฑ ํฌ์ ํด๊ฒฐํ๋ค.
const url = 'https://jsonplaceholder.typicode.com';
// id๊ฐ 1์ธ post์ userId๋ฅผ ์ทจ๋
promiseGet(`${url}/posts/1`)
// ์ทจ๋ํ post์ userId๋ก user ์ ๋๋ฅผ ์ทจ๋
.then(({ userId }) => promiseGet(`${url}/users/${userId}`))
.then(userInfo => console.log(userInfo))
.catch(err => console.error(err));
์ ์์ ์์ then โ then โ catch ์์๋ก ํ์ ์ฒ๋ฆฌ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. then, catch, finally ํ์ ์ฒ๋ฆฌ ๋ฉ์๋๋ ์ธ์ ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ฏ๋ก ์ฐ์์ ์ผ๋ก ํธ์ถํ ์ ์๋ค. ์ด๋ฅผ ํ๋ก๋ฏธ์ค ์ฒด์ด๋์ด๋ผ ํ๋ค.
Promidr๋ 5๊ฐ์ง ์ ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
Promise.resolve ์ Promise.reject ๋ฉ์๋๋ ์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ์ ๋ํํ์ฌ ํ๋ก๋ฏธ์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
// ๋ฐฐ์ด์ resolveํ๋ ํ๋ก๋ฏธ์ค๋ฅผ ์์ฑ
const resolvedPromise = Promise.resolve([1,2,3]);
resolvedPromise.then(console.log); // [1,2,3]
์ ์์ ๋ ๋ค์ ์์ ์ ๋์ผํ๊ฒ ๋์
const resolvedPromise = new Promise(resolve => resolve([1,2,3]));
resolvedPromise.then(console.log); // [1,2,3]
Promise.all ๋ฉ์๋๋ ์ฌ๋ฌ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋ชจ๋ ๋ณ๋ ฌ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค.
const requestData1 = () =>
new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () =>
new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () =>
new Promise(resolve => setTimeout(() => resolve(3), 1000));
// ์ธ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌ
const res = [];
requestData1()
.then(data => {
res.push(data);
return requestData2();
})
.then(data => {
res.push(data);
return requestData3();
})
.then(data => {
res.push(data);
console.log(res); // [1,2,3] ์ฝ 6์ด ์์
})
.catch(console.error);
์ ์์ ๋ ์ธ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌ. ์ฆ, ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์๋ฃํ๋ฉด ๋ค์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค. ๋ฐ๋ผ์ ์ ์์ ๋ ์ฒซ ๋ฒ์จฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ 3์ด, ๋ ๋ฒ์จฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ 2์ด, ์ธ ๋ฒ์งธ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ 1์ด๊ฐ ์์๋์ด ์ด 6์ด ์ด์ ๊ฑธ๋ฆฐ๋ค
Promise.all ๋ฉ์๋๋ ์ฌ๋ฌ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋ชจ๋ ๋ณ๋ ฌ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค๊ณ ํ๋ค. Promise.all ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์ธ ๊ฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํด๋ณด์
const requestData1 = () =>
new Promise((resolve) => setTimeout(() => resolve(1), 3000));
const requestData2 = () =>
new Promise((resolve) => setTimeout(() => resolve(2), 2000));
const requestData3 = () =>
new Promise((resolve) => setTimeout(() => resolve(3), 1000));
Promise.all([requestData1(), requestData2(), requestData3()])
.then(console.log) // [ 1, 2, 3 ] โ ์ฝ 3์ด ์์
.catch(console.error);
Promise.all ๋ฉ์๋๋ ํ๋ก๋ฏธ์ค๋ฅผ ์์๋ก ๊ฐ๋ ๋ฐฐ์ด ๋ฑ์ ์ดํฐ๋ฌ๋ธ์ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ฌ๋ฐ์ ๋ชจ๋ ํ๋ก๋ฏธ์ค๊ฐ ๋ชจ๋ fulfilled ์ํ๊ฐ ๋๋ฉด ๋ชจ๋ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์ด์ ์ ์ฅํด ์๋ก์ด ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค. ๊ฐ ํ๋ก๋ฏธ์ค๋ ๋ค์๊ณผ ๊ฐ์ด ๋์ํ๋ค.
Promise.all ๋ฉ์๋๋ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ๋ฐฐ์ด์ ๋ชจ๋ ํ๋ก๋ฏธ์ค๊ฐ ๋ชจ๋ fulfilled ์ํ๊ฐ ๋๋ฉด ์ข
๋ฃํ๋ค.
๋ชจ๋ ํ๋ก๋ฏธ์ค๊ฐ fullfilled ์ํ๊ฐ ๋๋ฉด resolve๋ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋ ๋ฐฐ์ด์ ์ ์ฅํด ์๋ก์ด ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค. ์ด๋ ์ฒซ ๋ฒ์จฐ ํ๋ก๋ฏธ์ค๊ฐ ๊ฐ์ฅ ๋์ค์ fulfilled ์ํ๊ฐ ๋์ด๋ Promise.all ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ํ๋ก๋ฏธ์ค๊ฐ resolve์ธ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ถํฐ ์ฐจ๋ก๋๋ก ๋ฐฐ์ด์ ์ ์ฅํด ๊ทธ ๋ฐฐ์ด์ resolveํ๋ ์๋ก์ด ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค.
Promise.all ๋ฉ์๋๋ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ๋ฐฐ์ด์ ํ๋ก๋ฏธ์ค๊ฐ ํ๋๋ผ๋ rejected ์ํ๊ฐ ๋๋ฉด ๋๋จธ์ง ํ๋ก๋ฏธ์ค๊ฐ fulfilled ์ํ๊ฐ ๋๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ฆ์ ์ข
๋ฃํ๋ค.
Promise.all([
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 1")), 3000)
),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 2")), 2000)
),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 3")), 1000)
),
])
.then(console.log)
.catch(console.log); // Error: Error 3
์ ์์ ์ ๊ฒฝ์ฐ ์ธ ๋ฒ์งธ ํ๋ก๋ฏธ์ค๊ฐ ๊ฐ์ ๋จผ์ rejected ์ํ๊ฐ ๋๋ฏ๋ก ์ธ ๋ฒ์จฐ ํ๋ก๋ฏธ์ค๊ฐ reject์ธ ์๋ฌ๊ฐ catch ๋ฉ์๋๋ก ์ ๋ฌ๋๋ค.
Promise.all ๋ฉ์๋๋ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์ดํฐ๋ฌ๋ธ์ ์์๊ฐ ํ๋ก๋ฏธ์ค๊ฐ ์๋ ๊ฒฝ์ฐ Promise.resolve ๋ฉ์๋๋ฅผ ํตํด ํ๋ก๋ฏธ์ค๋ก ๋ํํ๋ค.
Promise.all([
1, // => Promise.resolve(1)
2, // => Promise.resolve(2)
3, // => Promise.resolve(3)
])
.then(console.log) // [1, 2, 3]
.catch(console.log);
Promise.race ๋ฉ์๋๋ Promise.all ๋ฉ์๋์ ๋์ผํ๊ฒ ํ๋ก๋ฏธ์ค๋ฅผ ์์๋ก ๊ฐ๋ ๋ฐฐ์ด ๋ฑ์ ์ดํฐ๋ฌ๋ธ์ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค. Promise.race ๋ฉ์๋๋ Promise.all ๋ฉ์๋์ฒ๋ผ ๋ชจ๋ ํ๋ก๋ฏธ์ค๊ฐ fulfilled ์ํ๊ฐ ๋๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ์ฅ ๋จผ์ fulfilled ์ํ๊ฐ ๋ ํ๋ก๋ฏธ์ค์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ resolveํ๋ ์๋ก์ด ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค.
Promise.race([
new Promise((resolve) => setTimeout(() => resolve(1), 3000)), // 1
new Promise((resolve) => setTimeout(() => resolve(2), 2000)), // 2
new Promise((resolve) => setTimeout(() => resolve(3), 1000)), // 3
])
.then(console.log) // 3
.catch(console.log);
ํ๋ก๋ฏธ์ค๊ฐ rejected ์ํ๊ฐ ๋๋ฉด Promise.all ๋ฉ์๋์ ๋์ผํ๊ฒ ์ฒ๋ฆฌ๋๋ค. ์ฆ Promise.race ๋ฉ์๋์ ์ ๋ฌ๋ ํ๋ก๋ฏธ์ค๊ฐ ํ๋๋ผ๋ rejected ์ํ๊ฐ ๋๋ฉด ์๋ฌ๋ฅผ rejectํ๋ ์๋ก์ด ํ๋ก๋ฏธ์ค๋ฅผ ์ฆ์ ๋ฐํํ๋ค.
Promise.race([
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 1")), 3000)
),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 2")), 2000)
),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error 3")), 1000)
),
])
.then(console.log)
.catch(console.log); // Error: Error 3
Promise.allSettled ๋ฉ์๋๋ ํ๋ก๋ฏธ์ค๋ฅผ ์์๋ก ๊ฐ๋ ๋ฐฐ์ด ๋ฑ์ ์ดํฐ๋ฌ๋ธ์ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ฌ๋ฐ์ ํ๋ก๋ฏธ์ค๊ฐ ๋ชจ๋ settled ์ํ๊ฐ ๋๋ฉด ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์ด๋ก ๋ฐํํ๋ค. ES11์ ๋์ ๋ Promise.allSettled ๋ฉ์๋๋ IE๋ฅผ ์ ์ธํจ ๋๋ถ๋ถ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ง์ํ๋ค.
Promise.allSettled([
new Promise((resolve) => setTimeout(() => resolve(1), 2000)),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Error!")), 1000)
),
]).then(console.log);
/*
[
{status: "fulfilled", value: 1},
{status: "rejected", reason: Error: Error! at <anonymous>:3:54}
]
*/
๋ค์ ์์ ๋ฅผ ์ดํด๋ณด๊ณ ์ด๋ค ์์๋ก ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋ ์ง ์๊ฐํด๋ณด์.
setTimeout(() => console.log(1), 0);
Promise.resolve()
.then(() => console.log(2))
.then(() => console.log(3));
ํ๋ก๋ฏธ์ค์ ํ์ ์ฒ๋ฆฌ ๋ฉ์๋๋ ๋น๋๊ธฐ๋ก ๋์ํ๋ฏ๋ก 1 โ 2 โ 3์ ์์ผ๋ก ์ถ๋ ฅ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง 2 โ 3 โ 1์ ์์ผ๋ก ์ถ๋ ฅ๋๋ค. ๊ทธ ์ด์ ๋ ํ๋ก๋ฏธ์ค์ ํ์ ์ฒ๋ฆฌ ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์๋ ํ์คํฌ ํ๊ฐ ์๋๋ผ ๋ง์ดํฌ ๋กํ์คํฌ ํ์ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋ง์ดํฌ๋กํ์คํฌ ํ๋ ํ์คํฌ ํ์๋ ๋ณ๋์ ํ๋ค. ๋ง์ดํฌ๋กํ์คํฌ ํ์๋ ํ๋ก๋ฏธ์ค์ ํ๋ก๋ฏธ์ค์ ํ์ ์ฒ๋ฆฌ ๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์๊ฐ ์ผ์ ์ ์ฅ๋๋ค. ๊ทธ ์ธ์ ๋น๋๊ธฐ ํจ์์ ์ฝ๋ฐฑ ํจ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ํ์คํฌ ํ์ ์ผ์ ์ ์ฅ๋๋ค.
์ฝ๋ฐฑ ํจ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ผ์ ์ ์ฅํ๋ค๋ ์ ์์ ํ์คํฌ ํ์ ๋์ผํ์ง๋ง ๋ง์ดํฌ๋กํ์คํฌ ํ๋ ํ์คํฌ ํ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋๋ค ์ฆ, ์ด๋ฒคํธ ๋ฃจํ๋ ์ฝ ์คํ์ด ๋น๋ฉด ๋จผ์ ๋ง์ดํฌ๋กํ์คํฌ ํ์์ ๋๊ธฐํ๊ณ ์๋ ํจ์๋ฅผ ๊ฐ์ ธ์ ์คํํ๋ค. ์ดํ ๋ง์ดํฌ๋กํ์คํฌ ํ๊ฐ ๋น๋ฉด ํ์คํฌ ํ์์ ๋๊ธฐํ๊ณ ์๋ ํจ์๋ฅผ ๊ฐ์ ธ์ ์คํํ๋ค.
fetch ํจ์๋ XMLHttpRequest ๊ฐ์ฑ์ ๋ง์ฐฌ๊ฐ์ง๋ก HTTP ์์ฒญ ์ ์ก ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ Web API๋ค. fetch ํจ์๋ XMLHttpRequest ๊ฐ์ฑ๋ณด๋ค ์ฌ์ฉ๋ฒ์ด ๊ฐ๋จํ๊ณ ํ๋ก๋ฏธ์ค๋ฅผ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋ฐฑ ํจํด์ ๋จ์ ์์ ์์ ๋กญ๋ค. fetch ํจ์๋ ๋น๊ต์ ์ต๊ทผ์ ์ถ๊ฐ๋ Web API๋ก์ ์ธํฐ๋ท ์ต์คํ๋ก๋ฌ๋ฅผ ์ ์ธํ ๋๋ถ๋ถ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ ๊ณต.
fetch ํจ์์๋ HTTP ์์ฒญ์ ์ ์กํ URL๊ณผ HTTP ์์ฒญ ๋ฉ์๋, HTTP ์์ฒญ ํค๋, ํ์ด๋ก๋ ๋ฑ์ ์ค์ ํ ๊ฐ์ฒด๋ฅผ ์ ๋ฌ.
const promise = fetch(url [, options])
fetch ํจ์๋ HTTP ์๋ต์ ๋ํ๋ด๋ Response ๊ฐ์ฒด๋ฅผ ๋ํํ Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => console.log(response));
fetch ํจ์๋ HTTP ์๋ต์ ๋ํ๋ด๋ Response ๊ฐ์ฒด๋ฅผ ๋ํํ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ฏ๋ก ํ์ ์ฒ๋ฆฌ ๋ฉ์๋ thne์ ํตํด ํ๋ก๋ฏธ์ค๊ฐ resolveํ Response ๊ฐ์ฒด๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์๋ค. Response ๊ฐ์ฒด๋ HTTP ์๋ต์ ๋ํ๋ด๋ ๋ค์ํ ํ๋กํผํฐ๋ฅผ ์ ๊ณตํ๋ค.
Response.prototype์๋ Response ๊ฐ์ฒด์ ํฌํจ๋์ด ์๋ HTTP ์๋ต ๋ชธ์ฒด(response.body)๋ฅผ ์ํ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
์๋ฅผ ๋ค์ด, fetch ํจ์๊ฐ ๋ฐํํ ํ๋ก๋ฏธ์ค๊ฐ ๋ํํ๊ณ ์๋ MIME ํ์
์ด application/json์ธ HTTP ์๋ต ๋ชธ์ฒด๋ฅผ ์ทจ๋ํ๋ ค๋ฉด Response.prototype.json ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
Response.prototype.json ๋ฉ์๋๋ Response ๊ฐ์ฒด์์ HTTP ์๋ต ๋ชธ์ฒด๋ฅผ ์ญ์ง๋ ฌํํ๋ค.
fetch ํจ์๋ฅผ ์ฌ์ฉํ ๋๋ ์๋ฌ ์ฒ๋ฆฌ์ ์ฃผ์ํด์ผ ํ๋ค.
fetch("https://jsonplaceholder.typicode.com/todos/1")
// response๋ HTTP ์๋ต์ ๋ํ๋ด๋ Response ๊ฐ์ฒด์ด๋ค.
// json ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ Response ๊ฐ์ฒด์์ HTTP ์๋ต ๋ชธ์ฒด๋ฅผ ์ทจ๋ํ์ฌ ์ญ์ง๋ ฌํํ๋ค.
.then((response) => response.json())
// json์ ์ญ์ง๋ ฌํ๋ HTTP ์๋ต ๋ชธ์ฒด์ด๋ค.
.then((json) => console.log(json));
// {userId: 1, id: 1, title: "delectus aut autem", completed: false}
fetch ํจ์๋ฅผ ์ฌ์ฉํ ๋๋ ์๋ฌ ์ฒ๋ฆฌใ ์ฃผ์
const wrongUrl = 'https://jsonplaceholder.typicode.com/xxx/1';
// ๋ถ์ ์ ํ URL์ด ์ ์ฅ๋์๊ธฐ ๋๋ฌธ์ 404 Not Found ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
fetch(wrongUrl)
.then(() => console.log('ok'))
.cach(() => console.log('error'));
fetch ํจ์๊ฐ ๋ฐํํ๋ ํ๋ก๋ฏธ์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก 404 Not Found๋ 500 Internal Server Error์ ๊ฐ์ HTTP ์๋ฌ๊ฐ ๋ฐ์ํด๋ ์๋ฌ๋ฅผ rejectํ์ง ์๊ณ ๋ถ๋ฆฌ์ธ ํ์ ์ ok ์ํ๋ฅผ false๋ก ์ค์ ํ Response ๊ฐ์ฒด๋ฅผ resolveํ๋ค. ์คํ๋ผ์ธ ๋ฑ์ ๋คํธ์ํฌ ์ฅ์ ๋ CORS ์๋ฌ์ ์ํด ์์ฒญ์ด ์๋ฃ๋์ง ๋ชปํ ๊ฒฝ์ฐ์๋ง ํ๋ก๋ฏธ์ค๋ฅผ rejectํ๋ค.
๋ฐ๋ผ์ fetch ํจ์๋ฅผ ์ฌ์ฉํ ๋๋ ๋ค์๊ณผ ๊ฐ์ด fetch ํจ์๊ฐ ๋ฐํํ ํ๋ก๋ฏธ์ค๊ฐ resolveํ ๋ถ๋ฆฌ์ธ ํ์ ์ ok ์ํ๋ฅผ ํ์ธํด ๋ช ์์ ์ผ๋ก ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ํ์๊ฐ ์๋ค.
const wrongUrl = 'https://jsonplaceholder.typicode.com/xxx/1';
// ๋ถ์ ์ ํ URL์ด ์ ์ฅ๋์๊ธฐ ๋๋ฌธ์ 404 Not Found ์๋ฌ๊ฐ ๋ฐ์ํ๋ค
fetch(wrongUrl)
// response๋ HTTP ์๋ต์ ๋ํ๋ด๋ Response ๊ฐ์ฒด๋ค.
.then(response => {
if(!response.ok) throw new Error(response.statusText);
return response.json();
})
.then(todo => console.log(todo));
.catch(err => console.error(err));
์ฐธ๊ณ ๋ก axios๋ ๋ชจ๋ HTTP ์๋ฌ๋ฅผ rejcetํ๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ์๋ฌ๋ฅผ catch์์ ์ฒ๋ฆฌํ ์ ์์ด ํธ๋ฆฌํ๋ค. axios๋ ์ธํฐ์ ํฐ, ์์ฒญ ์ค์ ๋ฑ fetch๋ณด๋ค ๋ค์ํ ๊ธฐ๋ฅ์ ์ง์ํ๋ค.
request.get('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
if(!response.ok) throw new Error(response.statusTexT);
return response.json();
})
.then(todos => console.log(todos))
.catch(err => console.log(err));
// {userId : 1, id: 1, title: "delectus aut autem", completed: false}
request.post('https://jsonplaceholder.typicode.com/todos', {
userId: 1,
title: 'JavaScript',
completed: false
}).then(response => {
if(!response.ok) throw new Error(response.statusText);
return response.json();
})
.then(todos => console.log(todos))
.catch(err => console.error(err));
// {userId: 1, title: "JavaScript", completed: false, id: 201}
request.post('https://jsonplaceholder.typicode.com/todos', {
completed: true
}).then(response => {
if (!response.ok) throw new Error(response.statusText);
return response.json();
})
.then(todos => console.log(todos))
.catch(err => console.error(err));
// {userId: 1, id: 1, title: "delectus aut autem", completed: true}
request.delete('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
if(!response.ok) throw new Error(response.statusText);
return response.json();
})
.then(todos => console.log(todos))
.catch(err => console.error(err));