동기, 비동기 / Promise

햄은 개발 공부중·2023년 1월 18일
0
post-thumbnail

✏️ 동기, 비동기?

  • 동기(Blocking) : 하나의 작업이 끝나야 다른 작업 실행 (다른 작업의 실행을 막음)
  • 비동기 (Non-blocking) : 하나의 작업을 하는 도중에 다른 작업도 실행 (다른 작업의 실행을 막지 않음)

JavaScript는 싱글 스레드 기반으로 동작하기 때문에 동기적으로 작동하게 된다. 하지만 Node.js를 통해 비동기적으로 작동하게 만들수 있다!


✏️ Promise

비동기로 작동하는 코드를 제어할 수 있는 다른 방법은 Promise를 활용하는 것이다. 또한 Callback Hell을 방지하는 역할도 함!

new Promise

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

let promise = new Promise((resolve, reject) => {
	// 1. 정상적으로 처리되는 경우
	// resolve의 인자에 값을 전달할 수도 있음
	resolve(value);

	// 2. 에러가 발생하는 경우
	// reject의 인자에 에러메세지를 전달할 수도 있음
	reject(error);
});

Promise 객체의 내부 프로퍼티

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

  • State : 기본 상태는 pending(대기)이다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동했다면 fulfilled (이행)로 변경이 되고, 에러가 발생했다면 rejected (거부)가 된다.
  • Result : 처음은 undefined이다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동하여resolve(value)가 호출되면 value로, 에러가 발생하여 reject(error)가 호출되면 error로 변하게 된다.

Promise 내부 메서드

  • .Then : executor에 작성했던 코드들이 정상적으로 처리가 되었다면 resolve 함수를 호출하고 .then 메서드로 접근할 수 있다. 또한 .then 안에서 리턴한 값이 Promise면 Promise의 내부 프로퍼티 result를 다음 .then 의 콜백 함수의 인자로 받아오고, Promise가 아니라면 리턴한 값을 .then 의 콜백 함수의 인자로 받아올 수 있다.
  • .Catch : executor에 작성했던 코드들이 에러가 발생했을 경우에는 reject 함수를 호출하고 .catch 메서드로 접근할 수 있다.
  • Finally : executor에 작성했던 코드들의 정상 처리 여부와 상관없이 .finally 메서드로 접근할 수 있다.
    let promise = new Promise(function(resolve, reject) {
    	resolve("성공");
    });
    promise
    .then(value => {
    	console.log(value);
    	// "성공"
    })
    .catch(error => {
    	console.log(error);
    })
    .finally(() => {
    	console.log("성공이든 실패든 작동!");
    	// "성공이든 실패든 작동!"
    })```

Promise chaining

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

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

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

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));

🔥Async/Await (최종!)

Promise를 통해 비동기 코드의 순서를 제어할 수 있지만 Callback 함수와 같이 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Promise Hell이 발생하는 단점이 있기 때문에 JavaScript는 ES8에서 async/await키워드를 제공하기 시작했다. 이를 통해 복잡한 Promise 코드를 간결하게 작성할 수 있게 되었다. 사용법은 함수 앞에 async 키워드를 사용하고 async 함수 내에서만 await 키워드를 사용하면 된다. 이렇게 작성된 코드는 await 키워드가 작성된 코드가 동작하고 나서야 다음 순서의 코드가 동작하게 된다.

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

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

// 화살표 함수
const ArrowFunc = async () => {
	await 작성하고자 하는 코드
	...
}
const printAll = async () => {
 await printString('A');
 await printString('B');
 await printString('C');
};
profile
내가 보려고 정리하는 블로그🔥

0개의 댓글