ํ์ฌ ์คํ์ค์ธ task๊ฐ ์ข ๋ฃํ ๋ ๊น์ง, ๋ค์ task๊ฐ ๋๊ธฐํ๋ ๋ฐฉ์
๋ธ๋กํน
์์ ์ด ์ค๋จ๋๋ค๋ ์๋ฏธ์ด๋ค.
์ฆ, ๋คํธ์ํฌ ํต์ ์์ ์์ฒญ์ด ๋ฐ์ํ๊ณ ์๋ฃ๋ ๋๊น์ง ๋ชจ๋ ์ผ์ ์ค๋จํ ์ํ๋ก ๋๊ธฐํด์ผ ํ๋ ๊ฒ์ ๋ธ๋กํน ๋ฐฉ์์ด๋ผ๊ณ ํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ์ฐ๋ ๋ ์ธ์ด์ด๋ค.
ํ์ค์ฉ ๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ค.
ํ์ฌ ์คํ ์ค์ธ ์ฝ๋๊ฐ ์๋ฃ๋์ง ์์๋, ๋ค์ ์ฝ๋๋ก ๋์ด๊ฐ๋ค.
๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ํ์ํ ์ด์
์๋ฐ์คํฌ๋ฆฝํธ๋ ํ๋ฒ์ ํ๋์ task๋ง ์คํํ ์ ์๋ Single Thread ์ธ์ด์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฒ๋ฆฌ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ task๋ฅผ ์คํํ๋ฉด Blocking(์์ ์ค๋จ)ํ์์ด ๋ฐ์ํ๋ค.
์ด๋ฏธ์ง ์ถ์ฒ: https://adrianmejia.com/asynchronous-vs-synchronous-handling-concurrency-in-javascript/
setTimeout ๋น๋๊ธฐ ํจ์
ํ์ง๋ง... ์๋ฐ์ค๋ฆฝ๋ ์ฑ๊ธ์ค๋ ๋์ธ๋ฐ ์ setTimeout์ด ๋จนํ๋?
๊ฒฐ๋ก Web APIs๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ธ๋ผ์ฐ์ ๋ ์๊ฐ๋ณด๋ค ๋ ๋ง์ ๊ธฐ๋ฅ์ ํด์ค๋ค. ๋ธ๋ผ์ฐ์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง๋ง ์๋๊ฒ ์๋๋ผ Web API๋ ์๋ค. ์น API ์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด์๋ ๋ณ๊ฐ๋ก ์ฌ๋ฌ API๋ฅผ ์ ๊ณตํ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์๋๋ผ ๋ณ๋์ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ ์คํ๋๋ค. ์ด ํ๊ฒฝ์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์ด๋ค.
์๋ฒ์ ํต์ ํ๊ธฐ ์ํด XMLHttpRequest
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ.
JSON, XML, HTML
๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ ํ
์คํธ ํ์ ๋ฑ์ ํฌํจํ ๋ค์ํ ํฌ๋งท์ ๊ตํ ๊ฐ๋ฅํจ์์ ๋งค๊ฐ๋ณ์๊ฐ ํจ์์ผ ๋, ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ํจ์
๊ตฌ์กฐ
let val = function(๐){
return ๐
}
function fn(arg){
arg()
}
fn(val)
val
ํจ์๋ ํ์ฌ ๋ฐ๋ก ์คํ๋์ง๋ ์์ง๋ง ๋ค๋ฅธ ํจ์์ ์
๋ ฅ๊ฐ์ผ๋ก ์ ๋ฌ๋์ด์ ๋ค๋ฅธ ํจ์์ ์ํด์ ๋์ค์ ํธ์ถ๋๋ค๋ผ ํด์ ์ฝ๋ฐฑํจ์
๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ฝ๋ฐฑ์ง์ฅ(callback hell)
ํจ์ ์์ ํจ์๊ฐ ๋ฐ๋ณต๋์ด ๋ค์ฌ์ฐ๊ธฐ ์์ค์ด ๊ฐ๋นํ๊ธฐ ํ๋ค ์ ๋๋ก ๊น์ด์ง๋ ํ์
์์ )timer(1000,function(){ console.log('์์ '); timer(1000,function(){ console.log('์์ '); timer(1000,function(){ console.log('์์ '); }); }); });
Promise๊ฐ์ฒด๋ javascript์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ง์ํ๋ ๊ฐ์ฒด ์ค ํ๋์ด๋ค.
๊ธฐ๋ณธ ํํ
const myPromise = new Promise((resolve, reject)=>{
//๊ตฌํ ..
})
promise๊ฐ ์์ฑ๋ ๋ ํ๋ก๋ฏธ์ค ์์์๋ ์ฝ๋ฐฑํจ์๋ ์๋์ ์ผ๋ก ์์ฑ๋๋ค.
resolve
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.reject
๋ฉ์๋์ ์ธ์๋ก ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ค. ์ด ์๋ฌ ๋ฉ์์ง๋ Promise ๊ฐ์ฒด์ ํ์ ์ฒ๋ฆฌ ๋ฉ์๋๋ก ์ ๋ฌ๋๋ค.ํ์ ์ฒ๋ฆฌ ๋ฉ์๋์๋ ๋ํ์ ์ธ then(Promise ๋ฐํ)
๊ณผ catch(์์ธ)
๊ฐ ์๋ค.
ํ๋ก๋ฏธ์ค๋ฅผ ์ฌ์ฉํ ๋ ์์์ผ ํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋
์ด ๋ฐ๋ก ํ๋ก๋ฏธ์ค ์ํ(states)์
๋๋ค. ์ฌ๊ธฐ์ ๋งํ๋ ์ํ๋ ํ๋ก๋ฏธ์ค์ ์ฒ๋ฆฌ ๊ณผ์ ์ ์๋ฏธํ๋ค. new Promise()
๋ก ํ๋ก๋ฏธ์ค๋ฅผ ์์ฑํ๊ณ ์ข
๋ฃ๋ ๋๊น์ง 3๊ฐ์ง ์ํ๋ฅผ ๊ฐ์ต๋๋ค.
new Promise()
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋๊ธฐ(Pending) ์ํ๊ฐ ๋๋ค.
new Promise()
new Promise(function(resolve,reject){
//...
})
์ฌ๊ธฐ์ ์ฝ๋ฐฑ ํจ์์ ์ธ์ resolve
๋ฅผ ์๋์ ๊ฐ์ด ์คํํ๋ฉด ์ดํ(Fulfilled) ์ํ๊ฐ ๋๋ค.
new Promise(function(resolve, reject){
resolve();
})
function getData(){
return new Promise(function(resolve, reject){
let data = 100;
resolve(data);
})
}
//resolve()์ ๊ฒฐ๊ณผ ๊ฐ data๋ฅผ resolvedData๋ก ๋ฐ์
getData().then(function(resolvedData){
console.log(resolvedData); //100
});
ํ๋ก๋ฏธ์ค์ '์ดํ' ์ํ๋ฅผ ์ข ๋ค๋ฅด๊ฒ ํํํด๋ณด๋ฉด '์๋ฃ' ์ ๋๋ค.
new Promise()
๋ก ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด ์ฝ๋ฐฑ ํจ์ ์ธ์๋ก resolve
์ reject
๋ฅผ ์ฌ์ฉํ ์ ์๋ค๊ณ ํ์ต๋๋ค. ์ฌ๊ธฐ reject
๋ฅผ ์๋์ ๊ฐ์ด ํธ์ถํ๋ฉด ์คํจ(rejected) ์ํ๊ฐ ๋๋ค.
new Promise(function(resolve, reject){
reject();
})
๊ทธ๋ฆฌ๊ณ , ์คํจ ์ํ๊ฐ ๋๋ฉด ์คํจํ ์ด์ (์คํจ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ ๊ฐ)๋ฅผ catch()
๋ก ๋ฐ์ ์ ์๋ค.
getData().then().catch(function(err){
console.log(err);
})
fetch()
๋ ๋คํธ์ํฌ ํต์ ํจ์์ด๋ฉฐ ๋ํ์ ์ผ๋ก Promise ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ํจ์์ด๋ค.
fetch()
์ Return ๊ฐ์ Promise ๋ฐ์ดํฐํ์
์ ๋ฆฌํดํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด Promise ๋ฐ์ดํฐํ์ ์ response Object๋ฅผ ๋๋ ค์ค ๊ฒ์ด๋ค.
then()
,catch()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
then()
์ฝ๋๊ฐ ์ ๋๋ก ์ํ๋์์ ๋ ์๋.
- then() ํจ์ ์์๋ callback()๋ฅผ ์ ๋ ฅํ๋ค.
- callback() ์์๋ ์๋ต์ ๋ฐ์์ ๋ ์ํํ๋ ์ฝ๋๋ฅผ ์์ฑ.
- ์ฑ๊ณต์ ์ผ๋ก ์คํ๋๋ค๋ฉด response์๋ fetch()์ ๊ฒฐ๊ณผ๊ฐ ๋ค์ด์๋ค.
catch()
๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ์๋
- catch()์๋ callback()๋ฅผ ์ ๋ ฅํ๋ค.
- ๋น๋๊ธฐ ์์ ์ ์คํจํ์ ๋ ์ํํ๋ ์ฝ๋ ์์ฑ
- err์๋ ์๋ฌ ๊ด๋ จ ์ ๋ณด๋ค์ด ๋ค์ด์๋ค.
.then(function(response){ })
response ํ๋ผ๋ฏธํฐ์ ์์๋ ์ฌ๋ฌ๊ฐ์ง ์ ๋ณด(์๋ฒ์ ํต์ ๊ฒฐ๊ณผ,์๋ฒ์ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ํต์ ํ๋์ง ๋ฑ)๊ฐ ์ ์ฅ ๋์ด์๋ค.
response.json()
promise๋ then()์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ then()์์ ๋ then()์ด ๋ค์ด๊ฐ๊ณ ๋ค์ ๋ then()์ด ๋ค์ด๊ฐ๋ ๋ฐฉ์
fetch("https://jsonplaceholder.typicode.com/posts")
.then(function (response) {
response.json().then(function (data) {
console.log("data", data);
});
})
.catch(function (reason) {
console.log("reason", reason);
});
then()์์์ promise๋ฅผ return ํ๊ณ ๋ฐ๊นฅ์ชฝ์์๋ ๋ด๋ถ then()๊ณผ ์ธ๋ถ then()์ ์ฐ๊ฒฐํ๋ ๋ฐฉ์์ด๋ค.
fetch("https://jsonplaceholder.typicode.com/posts")
.then(function (response) {
return response.json();
})
.catch(function (response) {
console.log("response", response);
})
.then(function (data) {
console.log("data", data);
});
โ๏ธ๋๋ค ์ฅ๋จ์ ์ด ์์ง๋ง chaining๋ฐฉ์์ ๋ ๋ง์ด ์ฌ์ฉํ๋ค.
function timer(time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(time);
}, time);
});
}
timer(1000)
.then(function (time) {
//1000์ time์ธ์์ ๋ค์ด๊ฐ๋ค.
console.log("time:" + time);
return timer(time + 1000);
})
.then(function (time) {
console.log("time:" + time);
return timer(time + 1000);
})
.then(function (time) {
console.log("time:" + time);
});
//fetch ํจ์๋ฅผ ์คํํ๋ฉด Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
const [coins, setCoins] = useState([]);
useEffect(() => {
fetch("https://api.coinpaprika.com/v1/tickers?limit=10")
.then((response) => response.json())
.then((json) => setCoins(json));
setLoading(false);
}, []);
//useEffectํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ฒ๋ง ํต์ ํ๊ฒ ํ๋ค.
//fetch๋ก ์ป์ด์จ ๋ฐ์ดํฐ๊ฐ response๊ฐ์ response.json()์ ์ด์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ก ๋ฐํ.
//๋ณํ๋ ๊ฐ์ฒด๊ฐ์ setCoins๋ณ์์ ๋ฃ์ด state๊ฐ์ผ๋ก ๋ฃ์ด์ค๋ค.
async์ await๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ํจํด ์ค ๊ฐ์ฅ ์ต๊ทผ์ ๋์จ ๋ฌธ๋ฒ์ด๋ค.
.then()
๋จ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด ES7์ async & await์ด ๋ฑ์ฅํ ๊ฒ์ด๋ค..then()
์ด ๊ฑฐ์ ํ์ํ์ง ์๋ค. ๋ promise์์ ์ฌ์ฉํ๋ .catch ๋์ try/catch
๊ตฌ๋ฌธ์ ์ฌ์ฉํ ์ ์๋ ์ฅ์ ์ด ์๊ธด๋ค.function timer(time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(time);
}, time);
});
}
async function run() {
var time = await timer(1000);
console.log("time:" + time);
time = await timer(time + 1000);
console.log("time:" + time);
time = await timer(time + 1000);
console.log("time:" + time);
}
run();
function timer(time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(time);
}, time);
});
}
async function run() {
console.log("start");
var time = await timer(1000);
console.log("time:" + time);
time = await timer(time + 1000);
console.log("time:" + time);
time = await timer(time + 1000);
console.log("time:" + time);
console.log("end");
}
async function run2() {
console.log("parent start");
await run();
console.log("parent end");
}
run2();
//์์๋๋ก ๋์ํ๋ค.
//console.log(run()); -> promise ๋ฆฌํด -> ์ด๋ง์ run()์์๋ await์ ์ฌ์ฉํ ์ ์๋ค.
/*
๊ฒฐ๋ก : async๋ ํ๋ฒํ ํจ์๋ฅผ promise๋ฅผ ๋ฆฌํดํ๋ ๋น๋๊ธฐ์ ์ธ ํจ์๋ก
๋ง๋ค์ด์ฃผ๋ ํค์๋์ด๊ณ ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํจ์์์์๋ await ์ฌ์ฉํ ์ ์๋ค.
*/
async & await
& .then()
๋ณํ ํ์ฉ
async function run() {
console.log("start");
var time = await timer(1000);
console.log("time: " + time);
time = await timer(time + 1000);
console.log("time: " + time);
time = await timer(time + 1000);
console.log("time: " + time);
console.log("end");
return time;
// asyncํจ์์ return๊ฐ์ ๋ง๋ค์ด ์ค๋ค๋ฉด run2()ํจ์ ์ time์ ๊ฐ์ด ๋ค์ด๊ฐ๋ค.
}
async function run2() {
console.log("parent start");
var time = await run();
console.log("time:" + time);
console.log("parent end");
}
console.log("parent parent start");
run2().then(function () {
console.log("parnet parent end");
});
๋ฐ๋ณตํด์ async()ํจ์๋ฅผ ๋ค์ ๋ง๋ค์ด ์ฌ์ฉํ๊ณ ์ถ์ง ์์ ๋๋ ๋ง์ง๋ง์ then()
ํจ์๋ฅผ ์ฌ์ฉํด์ฃผ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
promise๊ฐ์ฒด์ ๋ฉ์๋์ธ fetch๋ก ํต์ ํ์ฌ await์ ์ด์ฉํ์ฌ json๋ณ์์ ๋ฃ์ด์ฃผ๊ณ asyncํจ์๋ก ๊ฐ์ธ์ฃผ์ด jsonํ์ ๋ฐ์ดํฐ๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ก ๋ณํํ๋ json()์ ์ด์ฉํ์ฌ getMovies ํจ์๋ก ๋ฃ์ด์ฃผ์๋ค.
const getMovies = async () => {
const json = await (
await fetch(
`https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year`
)
).json();
};
/*
const getMovies = async () =>{
const response = await fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year`);
const json = await response.json();
};
*/
๊ฒฐ๋ก
- promise์ async & await์ ์ฐจ์ด์ ์ ๋ช ํํ๊ฒ ์๊ณ ์จ์ผํ๋ค.
- ๋๋ค ๋น๋๊ธฐ ์คํ์ ํ๊ธฐ์ํ ๋ฐฉ๋ฒ
- ๋๋ค ๋น๋๊ธฐ ์คํ ๋ ๋ด์ฉ์ ๋๊ธฐ๊ฐ์ง๊ณ ์คํํ๊ณ ์ถ์ ๊ฒ์ด๋ค.
- async & await์ catch๋ผ๊ณ ํ๋ ๊ตฌ๋ฌธ์ ๋ณ๋๋ก ์ง์ํ์ง ์๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ธ ์ฒ๋ฆฌํ ์ ์๋ ๋ฌธ๋ฒ ์คtry, catch
๋ฌธ์ด ์๋ค.
try catch
๊ตฌ๋ฌธ ์์ async & await ์ฌ์ฉํ๋ ๊ฑธ ๋ฃ์ด ๋์ผ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉดcatch
์์ ์ก์ ๋ผ ์ ์๋ค.
์ฐธ๊ณ ์๋ฃ
Promise ๋ง๋๋ ๋ฐฉ๋ฒ
Promise states
์ฝ๋ฐฑํจ์ - ์ํ์ฝ๋ฉ
async & awiat - ์ํ์ฝ๋ฉ
๋ง์ด ์ฐธ๊ณ ํ ์๋ฃ