(JS)Promise, Async/Await

trina lee·2023년 5월 7일
  • 비동기 코드는 코드가 작성된 순서대로 작동되는 것이 아니라 동작이 완료되는 순서대로 작동하게 된다. 즉, 코드의 순서를 예측할 수 없다.

  • 코드를 실행할 때마다 순서가 바뀌는 것을 확인을 했다. 프로그래밍을 하면서 개발자가 제어할 수 없는 코드를 작성하는 것은 옳지 않다. 개발자는 언제나 예측가능한 코드를 작성하도록 노력해야 한다. 따라서, 비동기로 작동하는 코드를 제어할 수 있는 방법에 대해 잘 알고 있어야 한다.

1.Callback 함수를 활용
Callback Hell의 현상을 방지하기 위해 Promise가 사용되기 시작했다.

  1. Promise
    -Promise는 class이기 때문에 new 키워드를 통해 Promise 객체를 생성한다. 또한 Promise는 비동기 처리를 수행할 콜백 함수(executor)를 인수로 전달받는데 이 콜백 함수는 resolve, reject 함수를 인수로 전달받는다.

-new Promise가 반환하는 Promise 객체는 state, result 내부 프로퍼티를 갖는다. 하지만 직접 접근할 수 없고 .then, .catch, .finally의 메서드를 사용해야 접근이 가능하다.

  • State
    기본 상태는 pending(대기)이다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동했다면 fulfilled(이행)로 변경이 되고, 에러가 발생했다면 rejected(거부)가 된다.

  • Result
    처음은 undefined이다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동하여 resolve(value)가 호출되면 value로, 에러가 발생하여 reject(error)가 호출되면 error로 변한다.

let promise = new Promise(function(resolve, reject) {
	resolve("성공");
});

promise
.then(value => {
	console.log(value);
	// "성공"
})
.catch(error => {
	console.log(error);
})
.finally(() => {
	console.log("성공이든 실패든 작동!");
	// "성공이든 실패든 작동!"
})

-executor에 작성했던 코드들이 정상적으로 처리가 되었다면 resolve 함수를 호출하고 .then 메서드로 접근할 수 있다.
-executor에 작성했던 코드들이 에러가 발생했을 경우에는 reject 함수를 호출하고 .catch 메서드로 접근할 수 있다.
-executor에 작성했던 코드들의 정상 처리 여부와 상관없이 .finally 메서드로 접근할 수 있다.

- Promise chaining

Promise chaining가 필요하는 경우는 비동기 작업을 순차적으로 진행해야 하는 경우이다. Promise chaining이 가능한 이유는 .then, .catch, .finally 의 메서드들은 Promise를 리턴하기 때문이다. 따라서 .then을 통해 연결할 수 있고, 에러가 발생할 경우 .catch 로 처리하면 된다.

const result = [];
promiseOne()
  .then(value => {
    result.push(value);
    return promiseTwo();
  })
  .then(value => {
    result.push(value);
    return promiseThree();
  })
  .then(value => {
    result.push(value);
   console.log(result);  
	 // ['1초', '2초', '3초']
  })

-Promise chaining을 사용했을 경우는 코드들이 순차적으로 동작되기 때문에 총 6초의 시간이 걸린다.

- Promise.all()

Promise.all()은 여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용한다.
인자로는 배열을 받는다. 해당 배열에 있는 모든 Promise에서 executor 내 작성했던 코드들이 정상적으로 처리가 되었다면 결과를 배열에 저장해 새로운 Promise를 반환해 준다.

Promise.all([promiseOne(), promiseTwo(), promiseThree()])
  .then((value) => console.log(value))
  // ['1초', '2초', '3초']
  .catch((err) => console.log(err));

-Promise.all()은 비동기 작업들을 동시에 처리한다. 따라서 3초 안에 모든 작업이 종료된다. 또한 Promise chaining로 작성한 코드보다 간결해졌다.
-Promise.all()은 인자로 받는 배열에 있는 Promise 중 하나라도 에러가 발생하게 되면 나머지 Promise의 state와 상관없이 즉시 종료된다.

Promise를 통해 비동기 코드의 순서를 제어할 수 있지만 Callback 함수와 같이 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Promise Hell이 발생하는 단점이 있다.

3. Async/Await

-복잡한 Promise 코드를 간결하게 작성할 수 있게 되었다.
-await 키워드가 작성된 코드가 동작하고 나서야 다음 순서의 코드가 동작하게 된다.
-await은 async로 선언된 함수가 return(resolve)될 때 까지 기다려준다.

// 함수 선언식
async function funcDeclarations() {
	await 작성하고자 하는 코드
	...
}

// 함수 표현식
const funcExpression = async function () {
	await 작성하고자 하는 코드
	...
}

// 화살표 함수
const ArrowFunc = async () => {
	await 작성하고자 하는 코드
	...
}
profile
지금은 개발 모드

0개의 댓글