TIL 21.05.18

Jaemin Jung·2021년 5월 19일
0

Today I Learned

목록 보기
22/62
post-thumbnail

오늘한일

비동기적 처리에 대해서 핸들링 하는 방법인 Callback, Promise, async&await을 배웠다.

Achievement Goals

(이해한대로 작성하였기에 틀릴수도 있습니다. 계속 공부하며 수정해 나가겠습니다.)

  • 중첩된 callback의 단점, Promise 의 장점을 이해할 수 있다.
  • Promise 사용 패턴과 언어적인 특징들을 이해할 수 있다.
  • resolve, reject의 의미와, then, catch와의 관계를 이해할 수 있다.
  • Promise 에서 인자를 넘기는 방법에 대해 이해할 수 있다.
  • Promise의 세가지 상태를 이해할 수 있다.
  • Promise.all 의 사용법을 이해할 수 있다.
  • async/await keyword에 대해 이해하고, 작동 원리를 이해할 수 있다.

비동기적(Asynchronous) 처리

비동기적 처리 상황이 좋게 작용하지 않을때가 있다.
내가 작성한 코드중 서버에서 데이터를 받아오는 코드가 있을때
데이터를 받아오는 시간이 2초 소요된다고 하면, 2초 소요를 기다리지않고
다음코드를 실행하기 때문에 문제가 발생할 수 있다.

function caller () {
  let num2
  console.log(1)
  setTimeout(()=> {
    num2 = 2},2000)
  console.log(num2) 
} 

caller()// outPut -> 1,undefined

위 코드처럼 num2에 할당한 값을 다음 코드에서 사용해야할때 비동기적 처리가 된다면,
할당이 되기전에 이미 다음코드를 실행해버려서 undefined가 출력된다.

Callback Hell

이를 해결하기위해 콜백 함수를 사용하여 특정 로직이 끝났을때 원하는 동작을 실행시킬 수 있다.

const Asynchronous = (num, callback) => {
  setTimeout(() => {
    console.log(num); 
    callback();
  },2000)
}

Asynchronous(1, () => {
  Asynchronous(2, () => {
    Asynchronous(3, () => {
      console.log(`finish`)
    })
  })
})
//outPut -> 1,2,3,'finish'

예시는 3번의 콜백이 있었지만 만약 100번 1000번 콜백을 진행야하는 상황이라면?
코드는 작성할 수 있겠지만, 작성하다 실수가 있을 수 있고, 가독성이 매우 떨어져서
만약 문제가 생겼을때 디버깅 작업이 매우 힘들어질것이다.
이를 Callback Hell이라고 한다.
Callback Hell을 해결하는 방법에는 Promise나 Async를 사용하는 방법이있다.

Promise

ES6부터 도입된 Promise는 자바스크립트 비동기 처리에 사용되는 객체이다.
Callback함수로 비동기 처리를 컨트롤 하는것 보다 가독성이 좋고 코드도 간결해진다.

기본문법은 class와 비슷하며, 생성할때 콜백함수를 선언하고,
그 내부에는 2가지의 콜백함수를 인자로 받는다.(resolve, reject)
Promise를 사용할때 주의할점은 생성하는 순간 콜백함수가 바로 실행이된다는점이다.

const promise = new Promise((resolve,reject)=>{
  //doing something && (resolve() || reject())
})

3가지 상태(states)

Promise는 3가지의 상태를 가지고있다.

  • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태

    • new Promise() 메서드를 호출하면 대기(Pending)상태가 된다.
  • Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

    • 비동기 처리가 완료되었을때, 콜백함수의 인자 resolve를 실행하면 이행(Fulfilled) 상태가 된다.
      이때 resolve는 인자로 실행 결과를 받는다.
  • Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

    • 비동기 처리가 실패하였을때, 콜백함수의 인자 reject를 실행하면 실패(Rejected) 상태가 된다.
      이때 reject는 인자로 new Error()를 작성하여 error 메세지를 표출한다.

Promise Chaining

Promise를 실행한 결과가 성공적이라면 (resolve)
.then()을 이용하여 결과값을 넘겨받을 수 있다.
.then()은 앞서 실행한 Promise가 잘 작동하면 그 값을 인자로 받아 행동을 실행한다.

new Promise(function(resolve, reject){
  setTimeout(function() {
    resolve(1);
  }, 2000);
})
.then(console.log) // outPut -> 1

.then()을 여러번 이용하여 여러 비동기 처리를 순차적으로 실행할 수 있다.
아래의 코드는 내부에서 return문으로 다음 .then()으로 값을 넘겨준다.

new Promise(function(resolve, reject){
  setTimeout(function() {
    resolve(1);
  }, 2000);
})
.then(function(result) {
  console.log(result); // 1
  return result + 10;
})
.then(function(result) {
  console.log(result); // 11
  return result + 20;
})
.then(function(result) {
  console.log(result); // 31
});

출처 https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

promise를 실행한 결과가 실패적이라면(reject) 에러코드를 전달하게 된다.
이때 에러코드를 .catch()를 이용하여 핸들링이 가능하다.
.then()으로도 핸들링이 가능하다고는 하나, .catch()의 사용을 권장한다고 한다.
.catch()는 reject()의 값이나, 에러코드(실패한 이유)를 전달받는다.

// catch()로 오류를 감지하는 코드
function getData() {
  return new Promise(function(resolve, reject) {
    resolve('hi');
  });
}

getData().then(function(result) {
  console.log(result); // hi
  throw new Error("Error in then()");
}).catch(function(err) {
  console.log('then error : ', err); // then error :  Error: Error in then()
});

출처 https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

async & await

비동기적 처리 코드는 Callback을 사용해야지 실행 순서가 보장받는다.
하지만 Callback 사고방식에 익숙하지 않은 사람들은 코드를 읽는데 많이 어려움이 있을것이다.

async와 await은 비동기적 코드를 동기적으로 실행되는것처럼 보이게 해준다.

async & await 사용법

async는 함수 선언 앞에 작성하여 함수 내부를 Promise로 동작하게 만들어준다.
아래는 Promise를 사용한 코드와 async를 사용한 코드를 보여준다.
둘다 동일하게 동작한다.

function user () {
  return new Promise ((resolve, reject) => {
    resolve('james')
  });
}
user().then(console.log)// outPut -> 'james'

//--------------------------------------------------------

async function user2 () {
	return 'james'
}
user2().then(console.log)// outPut -> 'james'

await은 async함수 내부에 작성 가능하고
await을 통해 비동기 처리 메서드가 처리될때까지 기다려주는개념이다.

 async function 함수명() {
  await 비동기_처리_메서드_명();
}

실사용 예제

비동기 처리를 해주는 메소드를 Promise를 통해 작성하고,
이를 async함수를 통해 값을 받아오는 작업이다.

function getName () {
  return new Promise ((resolve, reject) => {
    setTimeout (() => {
    const result = 'james';
      resolve(result)
    },3000) 
  })
}

async function consoleName() {
  const final = await getName()
  console.log(final)
}

consoleName() // outPut -> 'james'

Promise를 이용할때에는 resolve의 값을 .then()의 함수를 이용해서 받아왔지만,
이를 async로 값을 받아왔다

참고 사이트

https://velog.io/@eensungkim/Callback-TIL-43%EC%9D%BC%EC%B0%A8
https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

profile
내가 보려고 쓰는 블로그

0개의 댓글