JavaScript는 동기적으로 작동한다.
이는 호이스팅(hoisting)된 후부터 코드를 순서대로
동기적으로 실행시킨다는 것이다.
Hoisting이란, var, 선언된 함수를 코드의 제일 위로
올라가 가장 먼저 정의되는 것을 뜻한다.
Callback Function이란, 선언된 함수를
나중에 실행 시키는 것을 말한다.
console.log('1');
setTimeout(function () {
console.log('2');
}, 1000);
console.log('3');
위 코드의 결과값은 1, 3, 2로 출력된다.
여기서 function은 setTimeout이라는
API때문에 1000ms이후 실행하게 된다.
이렇게 setTimeout의 parameter로 전달된 함수는
hoisting되지 않고 setTimeout이 실행된 후에 실행된다.
이런 실행방식 때문에 callback function이라고 하며
비동기 처리 함수라고도 한다.
다만 이런 callback function도 동기적으로 처리하는 방법이 있다.
function printImmediately(print) {
print();
}
printImmediately(() => console.log('Hello'));
이런식으로 작성하면 동기적으로 처리할 수 있다.
프로그래밍 언어마다 callback function을 다루는 방식은 다 다르다.
콜백 함수를 너무 많이 사용하다보면
다음과 같은 문제점이 생길수 있다.
비동기 처리를 간편하게 처리할 수 있도록 도와주는 object이다.
정해진 기능이 정상적으로 작동한다면 성공의 메세지와 함께
처리된 결과값을 전달해 주며
만약 기능이 제대로 작동하지 않으면 에러를 보내준다.
Promise는 JavaScript에 들어있는 object이며
비동기 처리를 위해 만들어졌다.
Promise가 만들어져서 지정된 행동을 수행 중일 때는
Pending 상태가 된다.
반대로 행동을 성공적으로 끝냈을 때는 fulfilled 상태가 된다.
또는 행동을 수행할 수 없거나 에러가 난 경우는 rejected 상태가 된다.
const promise = new Promise(resolve, reject) => {
console.log('doing something...')
resolve('pangho')
// reject(new Error('no network'));
}
Promise는 Class로 만들 수 있으며 만들때 executor라는 콜백 함수를
넣어줘야 하며 이 안에는 2가지 콜백 함수를 받아야 한다.
기능을 정상적으로 수행해 마지막으로 데이터를 전달해 주는 함수
기능 수행 중 문제가 생겼을 때 호출하게되는 함수
주로 Error라는 object를 통해 데이터를 전달한다.
어떤 에러가 발생했는지 이유를 잘 명시해 줘야 한다.
promise 안에서는 주로 무거운 일들을 처리하게 된다
주로 네트워크에서 데이터를 받아오거나
파일을 읽어오는 것들을 비동기 처리 하는것이 좋다.
Promise 생성 시 주의 사항
3가지 값을 통해 데이터를 받아올 수 있다.
promise
.then(value => {
console.log(value);
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log('finally')
});
Promise의 값이 정상적으로 수행된다면
Promise의 resolve 데이터를 받아와 지정된 작업을 수행한다.
기능 수행을 완료하면 Promise를 return한다.
Promise의 값이 정상적으로 수행되지 않는다면
Promise의 reject의 데이터를 받아와 지정된 작업을 수행한다.
만약 catch를 사용하지 않으면 Uncaught 에러가 출력된다.
이렇게 출력된 에러를 잡아 콘솔 로그에 출력 시킨다.
기능 수행의 성공 실패에 관계 없이 마지막에 데이터를 출력한다.
Promise를 여러개 연결해서 작성하는 방법이다.
const fetchNumber = new Promise ((resolve, reject) => resolve(1));
fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
return new Promise((resolve, reject) => resolve(num - 1));
})
.then(num => console.log(num));
이렇게 .then을 작성하여 데이터를 바로 전달 할 수 있지만
또 다른 비동기 Promise를 전달할수도 있다.
const getHen = () =>
new Promise ((resolve, reject) => {
setTimeout(() => resoleve('🐔'), 1000;
});
const gerEgg = () =>
new Promise ((resolve, reject) => {
setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000;
});
const cook = () =>
new Promise ((resolve, reject) => {
setTimeout(() => resoleve(`${egg} => 🍳`), 1000;
});
getHen()
.then(getEgg)
.catch(error => {
return '🦄';
})
.then(cook)
.then(console.log)
.catch(console.log);
에러가 발생했을 때 잡지 못하면 작업을 수행할 수 없게되기 때문에
잘 처리하는 것이 중요하다.
위에 작성한 코드처럼 중간에 에러가 난 경우 대체할수도 있다.
Promise에 전달된 데이터들을 병렬적으로 모아주는 API이다.
작성 방법은 아래와 같다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return '🍎';
}
async function getBanana() {
await delay(1000);
return '🍌';
}
function pickAllfruits() {
return promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + '));
}
pickAllFruits().then(console.log);
사과와 바나나가 데이터로 전동되면
배열로 받아 문자열로 변경 후 출력된다.
Promise에 먼저 전송된 데이터를 출력한다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(2500);
return '🍎';
}
async function getBanana() {
await delay(1000);
return '🍌';
}
function pickOnlyOne() {
return promise.race([getApple(), getBanana()])
}
pickOnlyOne().then(console.log);
사과와 바나나중 먼저 전송되는 데이터를 받아 출력된다.
Promise를 좀더 간결하게 작성하여
동기적으로 실행되는 것처럼 보이게 만들어주는 코드이다.
async function fetchUser() {
return 'pangho';
}
const user = fetchUser();
user.then(console.log);
console.log(user)
async를 함수 앞에쓰면 자동적으로 Promise로 만들어진다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return '🍎';
}
async function getBanana() {
await delay(1000);
return '🍌';
}
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
await이라는 코드는 어떤 행동이 끝날때까지 기다렸다 끝나면
return값을 출력하는 코드이다.