🐣 혼자 공부하는 용도로 블로그를 보면서 작성한 거라 내용이 상당상당히 비슷합니다. 혹시나 보게 될 사람이 있으시다면 참고 바랍니다!
JavaScript는 기본적으로 비동기적으로 동작한다.
✅ 동기란?
코드를 위에서부터 순차적으로 읽어 처리하는 방식
작업 하나가 끝나면 그 다음 작업을 실행하는 방식
동시에 여러 작업을 수행할 수 없다.
흐름을 예측하기 쉽고, 실행되는 순서가 명확하다.
✅ 비동기란?
동시에 여러 작업을 수행할 수 있다.
흐름을 예측하기 어렵고 무엇이 먼저 완료될 것인지 보장할 수 없다.
📝 콜백함수는 A라는 함수의 파라미터에 B라는 함수를 사용하는 것인가? 그럼 여기서 B함수가 콜백함수가 되는건가?
setTimeout
은 인자로 들어온 콜백 함수를 예약하기만 하고 리턴한다.setTimeout
에 의해 기다리는 동작은 본래의 코드 흐름과는 상관없이 따로따로 독립적으로 동작한다.✅ 비동기의 단점
흐름을 예측하기 어렵다
동기 작업은 시간이 오래 걸리기는 하지만 무엇이 어떻게 진행되는지는 명확한 반면, 비동기 코드에서는 비교적 효율적이기는 하지만 무엇이 어떤 순서로 진행될지 예측하기가 상당히 어렵습니다.
콜백 지옥
비동기 작업에서 흐름제어를 하기 위해서는 그 특성상 각각의 비동기 작업이 "끝"났을 때 뒤에 이어질 작업을 미리 부여하는 식으로 흐름을 제어합니다.
예를 들면, setTimeout
과 같이 함수 단위로 작업을 처리하는 식으로 밖에 흐름 제어를 하지 못한다.
만약 비동기 작업이 주르륵 이어져있다면 콜백 지옥에 빠질 수 있다!!!
promise
에서는 작업의 단위를 함수로 관리한다.promise
는 비동기 작업의 단위이다promise
를 통해 비동기 작업들을 쉽게 관리할 수 있다.Promise
에서 요구하는 가장 기본적인 형태const promise01 = new Promise((resolve, reject) => {
// 비동기 작업...
});
위의 예시 설명
변수의 이름은 promise01
이며, const
로 선언했기 때문에 재할당이 되지 않는다. 하나의 변수로 끝까지 해당 Promise
를 관리하는 것이 가독성도 좋고 유지보수하기 좋음
new Promise(...)
으로 Promise
객체를 새롭게 만듬
생성자는 특별한 함수 하나를 인자로 받는다.
/ 이 함수의 이름은 executor
, 형태는 화살표 함수
executor
에 대한 설명
executor
는 첫번째 인수로 resolve
, 두 번째 인수로 reject
를 받는다
resolve
는 executor
내에서 호출할 수 있는 또 다른 함수, resolve
를 호출하게 된다면 "이 비동기 작업이 성공했어@!@!!!"라는 뜻이다.
reject
또한 executor
내에서 호출할 수 있는 또 다른 함수, reject
를 호출하게 된다면 "이 비동기 작업이 실패했어~.."라는 뜻이다.
Promise의 특징으로는 new Promise(...)
를 하는 순간 여기에 할당된 비동기 작업은 바로 시작된다. 앞서 이야기했듯 함수란 으레 정의하는 시점과 호출하는 시점이 다르다고 했었지만, new Promise
는 그냥 바로 호출한다.
Promise가 끝나고 난 다음의 동작을 우리가 설정해줄 수 있는데, 그것이 바로 then
메소드와 catch
이다.
then
메소드는 해당 Promise가 성공하고 난 후의 동작을 지정한다. / 인자로 함수를 받음catch
메소드는 해당 Promise가 실패하고 난 후의 동작을 지정한다. / 역시 인자로 함수를 받음const promise02 = new Promise((resolve, reject) => {
resolve();
});
promise02
.then(() => {
console.log("then!");
})
.catch(() => {
console.log("catch!");
});
// Promise에서 resolve가 호출되었기에 then!만 출력됨
비슷한 비동기 작업을 수행할 때마다 매번 new Promise(...)
을 할 필요없이 그냥 new Promise(...)
한 것을 그대로 리턴하는 함수를 만들어 사용하면 된다.
function startAsync(age) {
return new Promise((resolve, reject) => {
if(age > 20) resolve();
else reject();
});
}
const promise03 = startAsync(25);
promise03
.then(() => {
console.log("1 then!");
})
.catch(() => {
console.log("1 catch!!!");
});
const promise04 = startAsync(15);
promise04
.then(() => {
console.log("2 then!!!");
});
.catch(() => {
console.log("2 catch!!!");
});
이제 startAsync 함수를 호출하는 순간 new Promise(...)가 실행하게 되어 비동기 작업이 시작된다.
reject
가 수행된다.reject
혹은 resolve
만 유효하다. (executor 안에서 둘 중 하나가 호출되었다면 두 번째부터는 무시된다. throw 역시 마찬가지)Promise는 세 가지 상태를 지닌다. 대기(pending), 이행(fulfilled), 거부(rejected) 이며 fulfilled 일 때 then
, rejected일 때 catch
로 등록한 동작들이 실행된다.
Promise는 비동기 작업을 생성/시작하는 부분(new Promise(...))과 작업 이후의 동작 지정 부분(then, catch)을 분리함으로써 보다 유연한 설계를 가능하도록 한다.
참고자료