Promise
promise는 자바스크립트에서 이전 코드의 처리가 완료되기 전에 다음 코드를 실행하는 '비동기 처리'를 위한 객체이다.
이 비동기 처리의 특성에 의한 문제 중 하나가 이전 코드의 작업의 결과가 준비되지 않아 다음 코드 실행 시에 발생하는 에러이다.
이를 해결하기 위한 단순한 방법은 콜백 헬이 발생하는 방법인데, 간단히 소개하자면
db.query(query, param, (err, result) => {
if (err) //에러 처리
db.query(query2, result.data, (err, result2) => {
if (err) //에러 처리
db.query(query3, result2.data, (err, result3) => {
if (err) //에러 처리
//성공 반환
});
});
});
첫 번째 쿼리문이 처리 될때까지 기다리기 위해 쿼리문 코드 내부에 다음 쿼리를 삽입하는 형식이다.
문제는 이 방식은 에러를 해결할 수는 있으나, 코드의 복잡도가 증가하고 가독성이 떨어진다는 단점이 있다는 것이다.
이때 사용되는 것이 Promise 객체이다.
먼저, Promise 객체의 상태에 대해서 알아보자.
Promise 객체는 세가지 상태가 존재한다.
- pending: 객체의 초기 상태로 promise가 완료되기 전의 상태이다.
- fulfilled: 처리가 완료되어 결과 값은 반환된 상태, 즉, promise 비동기 작업이 이행된 상태이다.
- rejected: 처리에 실패하거나 에러가 발생하여 실패 결과를 반환한 상태, 즉, promise 비동기 작업이 실패하여 거부된 상태이다.
Promise 객체는 실행 후에 아래 두가지 상태 중 하나를 반환하고, 이를 통해 이후의 작업의 진행에 영향을 준다.
...
const resultData = await new Promise((resolve, reject) => {
db.query(query, param, (err, result) => {
if (err) {
return reject(err);
} else {
resolve(result);
}
});
});
const resultData2 = await new Promise((resolve, reject) => {
db.query(query2, resultData.data, (err, result2) => {
if (err) {
return reject(err);
} else {
resolve(result2);
}
});
});
...
이렇게 처리하면 result가 반환될때까지 result2는 실행되지 않는다.
첫 promise에서 에러가 발생하면, reject(err);로 rejected상태가 반환될 것이다.
그렇게 된다면 에러가 발생한 것으로 처리된다.
반대로 성공적으로 수행했다면, resolve(result);로 fulfilled 상태가 반환될 것이다.
이 경우에는 result가 결과값으로 반환되며, resultData에 저장된다.
이걸 좀 더 활용성 좋게 변형할 수도 있다.
const getData = (query, param) => {
return new Promise((resolve, reject) => {
db.query(query, param, (err, result) => {
if (err) {
return reject(err);
} else {
resolve(result);
}
});
});
};
...
async funtion fetchData() {
try{
const resultData = await getData(data);
const resultData2 = await getData2(resultData.data);
...
} catch (error) {
console.error(error);
}
}
async/await 대신에 then을 이용해도 된다.
Promise 정적 메서드
Promise에는 여러 정적 메서드가 있지만, 이번에 공부한 promise.all()에 대해서만 이야기하겠다.
Promise.all()은 여러 개의 비동기 작업을 동시에 처리할 때 사용된다.
그동안은 비동기 작업의 순차적인 완료를 위한 객체의 역할을 하였다면, promise.all()은 비동기 처리가 완료되어도 그 결과값을 반환하지 않고 다른 비동기 작업이 처리될 때까지 대기했다가 모든 결과를 배열로 반환한다.
const getData = (query, param) => {
return new Promise((resolve, reject) => {
db.query(query, param, (err, result) => {
if (err) {
return reject(err);
} else {
resolve(result);
}
});
});
};
const getData2 = (query2, param2) => {
return new Promise((resolve, reject) => {
db.query(query2, param2, (err, result) => {
if (err) {
return reject(err);
} else {
resolve(result);
}
});
});
};
const [resultData, resultData2] = await Promise.all([
getData(query, param),
getData2(query2, param2)
]);
이런식으로 사용하면 getData와 getData2를 동시에 처리 가능하다.
'WEB > JavaScript' 카테고리의 다른 글
[JS] Fuse.js (0) | 2024.12.12 |
---|---|
[JS] 옵셔널 체이닝: "?." (0) | 2024.11.14 |