본문 바로가기

WEB/JavaScript

[JS] Promise

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