본문 바로가기

개발 Note/JAVASCIPRT

[JAVASCRIPT] promise와 callback

자바스크립트에서 비동기 처리를 할 때 promise와 callback을 사용한다.

오늘은 이 둘의 차이점에 대해서 알아보려고 한다.

 


콜백 지옥(Callback hell)

콜백 지옥은 콜백 함수를 익명 함수로 연속해서 사용할 때 발생하는 문제이다. 이벤트 처리나 서버 통신과 같은 비동기적인 작업을 수행할 때 이런 형태가 자주 나타나는데, 가독성이 떨어지고 수정하기가 어렵다.

function async() {
    setTimeout((name) => {
      console.log(name);

        setTimeout((age) => {
              console.log(name + " " + age);

            setTimeout((sex) => {
                console.log(name + " " + age + " " + sex);
            }, 500, "M");

        },500, 21);

    }, 500, "Honggildong");
  }

 async();


0.5초마다 사람의 정보(이름, 나이, 성별)을 수집하고 출력한다.

>>>>>>>
Honggildong
Honggildong 21
Honggildong 21 M


각 콜백이 사람의 정보를 전달하고 정상적으로 출력하지만 callback이 점점 깊어져 가독성이 떨어지고 코드를 작성하는 데도 어려움이 있다.

이를 해결하는 방법으로는 익명 함수를 직접 분리해주는 방법과 Promise를 사용하는 방법이 있다.

 

 

- 코딩 패턴으로 해결(함수 선언)

function selectName(name) {
    console.log(name);
    setTimeout(selectAge, 500, name + " " + 21);
}

function selectAge(age) {
    console.log(age);
    setTimeout(selectSex, 500, age + " " + "M");
}

function selectSex(sex) {
    console.log(sex);
}

setTimeout(selectName, 500, 'Honggildong');


익명 함수를 모두 기명함수로 선언하여 분리해준 코드이다.

코드의 가독성을 높이고 순서를 따라간다면 코드를 이해하는 것도 개선된다.

그러나 일회성 함수를 전부 선언하는 것은 복잡한 코드에서는 오히려 헷갈릴 수 있다는 단점이 있다.

 

 

- Promise로 해결

  • Promise 알아보기
function async() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("성공");
        },500);
    })
}

async().then(res => {
    console.log(res)
});


resolve는 성공했을 때, reject는 에러가 발생했을 때 첫 번째 인자로 값을 넘길 수 있다.

resolve는 .then의 첫번째 인자로, reject는 .catch의 첫 번째 인자로 들어간다.

new 연산자와 함께 호출한 Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만 내부에 resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 .then 또는 .catch로 넘어가지 않는다. 따라서 비동기 작업이 완료될 때 resolve 또는 reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능하다.

 

 

  • promise로 callback지옥 해결하기
function async(result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(result);
            resolve(result);
        });
    });
}

async("Honggildong").then(res => {
    return async(res + " " + 21);
}).then(res => {
    return async(res + " " + "M");
});


위와 같이 코드의 깊이가 깊어지지 않아 가독성이 높아진다.

 

 

  • Promise + async/await
function selectPerson(param) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(param);
        });
    });
}

const person = async() => {
    let personInfo = '';
    let _selectPerson = async(param) => {
        personInfo += await selectPerson(param) + " ";
    };

    await _selectPerson('Honggildong');
    console.log(personInfo);
    await _selectPerson(21);
    console.log(personInfo);
    await _selectPerson('M');
    console.log(personInfo);
}

person();


비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고 함수 내부에서 실질적인 비동기 작업이 필요한 때마다 await를 표기하는 것으로 뒤의 내용을 Promise로 자동 전환한다. 해당 내용이 resolve된 이후에 다음으로 진행된다.

'개발 Note > JAVASCIPRT' 카테고리의 다른 글

[JAVASCRIPT] - vue.js로 차트 만들기(2)  (0) 2022.04.24
[JAVASCRIPT] - vue.js로 차트 만들기(1)  (0) 2022.04.17
[JAVASCRIPT] React  (0) 2022.04.01
[JAVASCRIPT] JQuery  (0) 2022.03.25