
❗ 콜백 지옥 탈출 방법! (비동기를 제어하는 법)
ES6의 Promise를 이용할 수 있다.
Promise는 new 연산자와 함께 호출하고 인자로 콜백을 받는다.
Promise는 Promise를 반환한다.
Promise는 호출될 때 바로 실행되지만 그 안에 콜백은 resolve, reject 둘 중 하나가 호출 되기 전에 then 또는 catch로 넘어가지 않는다.
resolve, reject 로 성공 혹은 실패로 결과 값을 나타내어 다음 작업을 체이닝할 수 있다. (즉, 비동기 제어가 가능하다.)
then으로 작업을 이어가기 위해서는 resolve() 함수를 호출한다.
작업을 중단 혹은 err 처리를 위해서는 reject() 함수를 호출한다.
예를 들면 서버에서 데이터를 받아올 때 받아오기에 성공할 경우 resolve()함수를 호출하고 실패할 경우 reject() 함수를 호출해서 서로 다른 작업으로 이어질 수 있게 만들 수 있다.
// Promise 기본 패턴 1 : 성공인 경우
function fn() {
new Promise((resolve, reject) => {
console.log('하나');
// 실패인 경우 reject() 함수를 호출하면 된다.
// 그러면 then()을 건너뛰고 catch()가 실행된다.
resolve();
})
.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('둘');
resolve();
}, 0);
});
})
.then(() => {
console.log('셋');
})
.catch((err) => {
console.log('err ', err);
});
}
// Promise 기본 패턴 2 : 성공인 경우
// 중요 포인트 : fn() 함수 안에서 Promise를 반환하였다.
function fn() {
return new Promise((resolve, reject) => resolve());
}
// Promise를 반환했기 때문에 number 변수도 Promise 타입이다.
const number = fn();
number
.then((p) => {
console.log(p);
console.log('하나');
})
.then(() => {
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('둘');
resolve();
}, 0);
});
})
.then(() => {
console.log('셋');
})
.catch((err) => {
console.log('err', err);
});
Promise를 이용해서 다음 비동기 함수로 값 전달하기
‘하나둘셋넷’텍스트 이어서 출력하기
// Promise 패턴 3 : 데이터 전달하기
// 중요 포인트 1. 데이터를 resolve()에 인자로 넣어 then 으로 전달할 수 있다.
// 중요 포인트 2. then에서 다음 then으로 데이터를 전달하기 위해서는 반드시 리턴값으로 전달해야한다.
function fn() {
new Promise((resolve, reject) => {
resolve('하나');
})
.then((data) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data + '둘');
}, 0);
})
})
.then((data) => {
return data + '셋'
})
.then((data) => {
console.log(data + '넷');
})
.catch((err) => {
console.log('err ', err);
});
}
여기서의 Promise는 배워야하는것들이 많아서 비동기를 제어하는 방법으로만…..
Promise + async/await를 이용하는 방법
ES2017에서 추가 된 async/await 문법을 이용한 방법이있다.
Promise로 비동기 처리를 하더라도 콜백 지옥이 연상되는것을 알수있었다. (then 안에 Promise 안에 then 안에 Promise안에….)
비동기 작업을 수행하고자 하는 함수 앞에 aynce를 표기하고, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await을 표기하는 것만으로 뒤의 내용을 Promise로 자동 전환하고 해당 내용이 resolve된 이후에야 다음으로 진행된다.
// '하나둘셋넷' 텍스트 이어서 출력하기
// 중요 포인트 1 : return을 하지 않았어도 자동으로 fn함수는 Promise를 return 한다.
// 중요 포인트 2 : await을 붙이 Promise는 Promise를 리턴하지 않는다. (resole에 인자로 전달한 데이터를 리턴한다.)
async function fn() {
let text = '하나';
text = text + await new Promise((resolve, reject) => {
setTimeout(() => {
resolve('둘');
}, 0);
});
text += '셋';
console.log(text + '넷');
}