Promise, async/await

Mooongs·2022년 5월 27일
0

코어자바스크립트

목록 보기
6/8
post-thumbnail

Synchronous(동기) / Asynchronous(비동기)

동기(synchronous)

현재 실행중인 코드가 완료되어야 다음 코드가 실행되는 것
자바스크립트는 단일 스레드(싱글 스레드)를 가지고 있기 때문에 동기식 언어

💡 스레드란? 프로그램이 작업을 완료하는 데 사용하는 단일 프로세스로, 하나의 스레드는 한 가지의 작업만 수행 가능하다

console.log('hi');
console.log('hello');
console.log('bye');

// hi
// hello
// bye

비동기(asynchronous)

하나의 동작이 완료되지 않아도 다음 코드가 실행되는 것
네트워크 통신이나 파일을 읽어오는 등 시간이 오래 걸리는 작업은 비동기적으로 처리하는 것이 좋다. 서버의 응답을 기다리는 동안 아무것도 실행되지 않으면 프로그램 실행 시간이 길어지고 화면이 멈춘 것처럼 보일 수 있기 때문이다.

❓ 그렇다면 싱글 스레드를 가지고 있는 자바스크립트가 비동기적으로 작업할 수 있는 이유는?
Web API가 멀티 스레드로 동작하기 때문!

console.log(1);
setTimeout(() => console.log(2), 1000);
console.log(3);

// 1
// 3
// 2 -> 1초 후 실행. 
// setTimeout: 지연 시간 뒤에 첫 번째 파라미터로 전달받은 콜백함수를 실행시키는 대표적 비동기 함수


Promise

콜백함수 대신에 비동기를 간편하게 처리할 수 있는 내장 Object로, ES6에서 도입되었다. 주로 서버에서 받아온 데이터를 화면에 나타낼 때 사용된다.

  1. Producer : 시간이 걸리는 일을 하는 주체
  2. Consumer : 원하는 데이터를 소비하는 주체
  3. Promise : 만들어진 제작 코드(producing code)와 이를 기다리는 소비 코드(consuming code)를 연결해주는 역할을 하는 객체이다.

Promise의 기본 문법

const promise = new Promise((resolve, reject) => {
	// executor (실행함수)
})

새로운 Promise 객체가 생성되면 바로 executor 함수가 자동으로 실행된다는 점을 유의하자! 이 부분에서 원하는 일이 처리되고, 성공 여부에 따라서 자바스크립트가 자체 제공하는 resolvereject 함수가 호출된다.

  • resolve : 일이 정상적으로 수행되었을 때 최종 데이터(value)를 전달해주는 콜백함수
  • reject : 문제가 생기면 에러 객체를 나타내는 error와 함께 호출되는 콜백함수

둘중 한가지는 반드시 호출해야 한다.

Promise의 상태

  • pending(대기)
  • 실행완료면 fulfilled(이행)
  • 문제가 생기면 rejected(거부)

이미 처리가 완료된 프로미스 이후에 resolve, reject를 호출하면 무시된다.

// 1. promise 제작 단계
// 성공
const promise = new Promise((resolve, reject) => {
	setTimeout(() => {
    	resolve('success') // 성공적으로 실행되면 2초 뒤 'success'라는 값 전달
    }, 2000);
});

// 실패
const promise = new Promise((resolve, reject) => {
	setTimeout(() => {
      	reject (new Error('no network')); // 실패하면 2초 뒤 Error 객체로 값 전달
    }, 2000);
});

// 2. promise 소비 단계 (then/catch로 값 처리)
promise
   	.then(value => {
    	console.log(value); 
  		// then 메서드는 성공 케이스만 다룬다 → resolve되면 'success'라는 값 출력
    })
	.catch(error => {
		console.log(error);  
 		// catch 메서드는 에러 케이스만 다룬다 → reject되면 'no network' 값 출력
	})
	.finally(() => {console.log('finally')})  // 성공 여부에 상관없이 무조건 출력

Promise chaining

밑의 예시는 사용자 로그인 인증 단계에서 사용될 수 있는 프로미스 체이닝을 보여주고 있다. (사용자 정보 파싱 → 인증 → 정보 표시)

var userInfo = {
  id: 'abc@naver.com',
  pw: '*****'
};

function parseValue() {
  return new Promise({
    // ...
  });
}
function auth() {
  return new Promise({
    // ...
  });
}
function display() {
  return new Promise({
    // ...
  });
}

getData(userInfo)
  .then(parseValue)
  .then(auth)
  .then(display);


async/await

콜백 함수와 Promise보다 비동기 처리를 더 깔끔하게 사용할 수 있게 해주는 문법으로,
ES2017에서 도입되었다.

Promise의 syntactic sugar이다.

💡 syntactic sugar : 문법적인 기능은 유지하되, 읽고 쓸 때 더욱 간편해지는 프로그래밍 문법

함수 앞에 async가 붙으면 반드시 프라미스를 반환하고, 프라미스가 아닌 것은 프라미스로 감싸 반환한다. await은 프라미스가 처리될 때까지 함수 실행을 기다렸다가 작동되며, async 함수 내에서만 작동한다는 점을 유의하자!

async/await의 기본 문법

async function func() {
	await // 비동기적으로 실행되는 코드
}

❗ 사용 예시

function fetchItems() {
  return new Promise(function(resolve, reject) {
    var items = [1,2,3];
    resolve(items)
  });
}

async function logItems() {
  var resultItems = await fetchItems(); 
  // 프라미스가 처리되면 프라미스 객체의 items 배열 결과값을 변수에 저장
  console.log(resultItems); // [1,2,3]
}

예외 처리

async/await에서는 try/catch로 예외 처리를 한다.

try {이걸 해보고 안되면} catch {이걸 해주세요}

try문이 잘 실행되면 catch문을 넘어간다.

❗ 사용 예시

async function f() {

  try {
    let response = await fetch('http://유효하지-않은-주소');
    let user = await response.json();
  } catch(err) {
    // fetch와 response.json에서 발행한 에러 모두를 여기서 잡는다.
    alert(err);
  }
}

f();


참고 자료

profile
#FE개발자🐣 #새로운건 #짜릿해

0개의 댓글