await/async - callback과 promise

0

저번글에서 js는 비동기적 아니라 동기적으로 동작하고,

web api (nodejs에선 c++ api) 때문에 js가 비동기적으로 동작하는 것처럼 보이는 것을 알았다.

그렇다면, 어떻게 비동기적으로 작동하는 코드를 순차적으로 수행할 수 있을까?

비동기적인 코드를 어떻게 순차적으로 수행할 수 있을까?

console.log('1');

setTimeout(function() {
	console.log('2');
}, 2000);

console.log('3');

저번 글에 따르면 console.log('1') 수행 -> setTimeout은 web api로 이동 -> console.log('3') 수행 -> stack이 다 비워지면, callBack queue에 있던 console.log('2')가 스택으로 이동하여 수행으로 위 코드는 실행 된다.

어떻게 하면 console.log('2')가 console.log('3') 보다 먼저 수행되게 할 수 있을까?

callback

정답은 callback함수를 사용하면 된다.

callback함수란 무엇일까? 간단하게 말하면 함수에 파라미터로 들어가는 함수이다.

사실 이미 callback함수를 사용하고 있었다. 위에서 setTimeout안에 들어가는 함수가 callback함수이다.

setTimeout은 정해진 시간 뒤에 callback함수를 실행해 달라는 함수였던 것이다.

console.log("1");

function console2(console3) {
  setTimeout(() => {
    console.log("2");
    console3();
  }, 2000);
}

function console3() {
  console.log("3");
}

console2(console3);

callback함수를 사용하여 console2함수의 파라미터로 console3함수가 들어가게 한다면,

당연히 setTimeout안에선 순차적으로 돌아가므로, console.log("3")은 console.log("2") 보다 나중에 출력되게 된다.

callback지옥

console.log("1");

function console2(console3) {
  setTimeout(() => {
    console.log("2");
    console3(console4);
  }, 2000);
}

function console3(console4) {
  console.log("3");
  console4();
}

function console4() {
  console.log("4");
}

console2(console3(console4));

만약 console2함수를 실행한다음, console3, console4...이렇게 순차적으로 실행하고 싶어서,

위 코드 처럼 함수의 파라미터로 callback함수를 넣고, 넣고,, 넣다보면 가독성이 매우 떨어지게 된다.

Promise

js에는 callback지옥을 벗어날 수 있는 Promise 객체가 있다.

Promise는 js 비동기 처리에 사용되는 객체이다.

console.log("1");

function console2() {
  return new Promise(function(resolve,reject) {
      setTimeout(() => {
        console.log("2");
        resolve();
      }, 2000);
  });
}

console2().then(function() {
    console.log("3");
});

위의 코드를 이렇게 바꿀 수 있다. setTimeout코드를 Promise 객체에 넣어준 것이다.

new Promise로 생성된 객체는 Pending<대기> Fulfilled<이행> Rejected<실패> 중 한가지 상태를 갖는다.

Pending

new Promise();

이렇게 Promise객체를 만들면, 대기 상태가 된다.

sequelize에서, 데이터를 받아와서 front로 보낼때 자꾸 undefined가 떠서 console에 찍어보면

pending이라는 문구가 뜬 것을 자주 확인 할 수 있다.

await를 써주지 않아서 대기하지 않고, 다음 코드로 넘어가버려서 pending상태로 출력되는 것이였다.

Fulfilled

new Promise(function(resolve, reject) {
  resolve();
});

Promise 객체는 콜백함수를 선언할 수 있고, 콜백함수는 인자로 resolve와 reject를 가지는데,

new Promise(function(resolve, reject) {
  resolve("success!");
}).then(function(result) {
  console.log(result);
});

resolve()를 실행하면, 이행 상태가 되고 then의 callback함수의 parameter를 통해 결과값을 받을 수 있다.

Rejected

new Promise(function(resolve, reject) {
  reject("error!");
}).then(function(result) {
  console.log("success!");
}).catch(function(error) {
  console.log(error);
})

resolve()를 실행하면, 실패 상태가 되고 catch의 callback함수의 parameter를 통해 실패 원인을 알 수 있다.

console.log("1");

new Promise(function(resolve, reject) {
  setTimeout(() => {
    console.log("2");
    resolve();
  }, 2000);
}).then(function() {
    new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("3");
        resolve();
      }, 3000);
    }).then(function() {
    	new Promise(function(resolve, reject) {
          setTimeout(() => {
            console.log("4");
            resolve();
          }, 4000);
        }).then(function() {
            setTimeout(() => {
               console.log("5");
            }, 5000);
        })
    })
})

이렇게 하면 위의 callback지옥을 해결하고 무슨 코드인지 보기 편해진다.

사실 편해진것..까지는 모르겠고 알아보기가 더 편한건 사실이다.

then이라는 함수때문에 아 이걸 해야 다음 코드가 실행되구나 라는 것을 이해하기 쉬워졌을 뿐이다.

profile
https://www.youtube.com/watch?v=__9qLP846JE

0개의 댓글