JS Promise, await

강정우·2022년 10월 12일
0

JavaScript

목록 보기
22/53
post-thumbnail

Promise

Promise API 예시

  • Promise API는 비동기 API중 하나이다.
  • Task Queue가 아닌 Job Queue 혹은 microtask queue를 사용한다.
  • Job Queue는 Task Queue보다 우선 순위가 높다.
setTimeout(() => {
	console.log("타임아웃1");
}, 0);

Promise.resolve().then(() => console.log("프로미스1"));

setTimeout(() => {
	console.log("타임아웃2");
}, 0);

Promise.resolve().then(() => console.log("프로미스2");

// 프로미스1 프로미스2
// 타임아웃1 타임아웃2
  • 즉, Promise의 처리가 setTimeout의 처리보다 먼저다.

Promise

  • 비동기 작업을 표현하는 JS객체
  • 비동기 작업의 진행, 성공, 실패 상태를 표현한다.
  • 비동기 처리의 순서를 표현할 수 있다.
  • 만약 비동기 API가 바로 실행된다면 Pending 상태에 접어들게 된다.
  • 위 사진을 설명하자면 .then 메서드가 있고 이때 2개의 콜백 함수를 넣을 수 있고 만약 1개의 함수만 넣었다면 반드시 catch 구문이 있어야 한다.

Promise 생성자

let promise = new 
Promise((resolve, reject)=>{
	if(Math.random()<<0.5){ 
    	return reject("실패") 
    }
	resolve(10)
})
  • new Promise(callback)
  • callback 함수는 (resolve, reject) 두 인자를 받는다.
  • Promise가 성공했을 때 resolve를 호출한다.
  • Promise가 실패했을 때 reject를 호출한다.

Promise 메서드

promise
	.then(data => {
    	console.log("성공 :", data)
    })
    .catch(e => {
    	console.log("실패 :", e)
    })
    .finally(() => {
    	console.log("promise 종료")
    })
  • then() 메서드에 성공했을 때 실행할 콜백 함수를 인자로 넘긴다.
  • catch() 메서드에 실패했을 때 실행할 콜백 함수를 인자로 넘긴다.
  • finally() 메서드는 성공/실패 여부와 상관없이 모두 실행할 콜백 함수를 인자로 넘긴다.
  • then(callback1, callback2)로 callback1의 자리에 성공, callback2의 자리에 실패 메서드를 인자로 넘길 수 있다.

Promise 메서드 체인

promise
	.then(data => {
    	return fetchUser(data)
    })
    .then(user => {
    	console.log("User :", user)
    })
    .catch(e => {
    	console.log("실패 :", e)
    })
  • then/catch 메서드가 또 다른 promise를 리턴하여, 비동기 코드에 순서를 부여한다. 즉, 적힌 순서대로 작동을 시키며 순서를 부여할 수 있다.
  • 이렇게 동일한 객체에 메서드를 연결할 수 있는 것을 체이닝이라 한다.
  • 함수를 호출한 주체가 함수를 끝낸 뒤 자기 자신을 리턴하도록 하여 구현한다. 예를 들어 new Promise() 같은 constructor라든지, .then()이라든지 모두 return this 코드를 숨겨두고 있다.

Promise.resolve, Promise.reject

// Promise 메서드의 성공시
Promise
	.resolve(10)
    .then(console.log)

// Promise 메서드의 실패시
Promise
	.reject("Error")
    .catch(console.log)
  • Promise.resolve 함수는 성공한 Promise를 바로 반환한다.
  • Promise.reject 함수는 실패한 Promise를 바로 반환한다.
  • 인위적으로 Promise 메서드 체인을 만들 수 있다.
  • 비동기 코드로 진행해야 하는 상황 등에 유용하게 사용할 수 있다.

Promise.all

Promise.all([
	promise1,
    promise2,
    promise3
])
	.then(values => {
    	console.log("모두 성공 :", values)
    })
    .catch(e => {
    	console.log("하나라도 실패 :", e)
    })
  • Promise.all은 Promise의 배열을 받아 모두 성공 시 각 Promise의 resolved 값을 배열로 반환한다.
  • 하나의 Promise라도 실패할 시, 가장 먼저 실패한 Promise의 이유를 반환한다.

실습 유저 주소 검색 폼 구현하기

  function searchAddress() {
    error = '';
    
    `findUserByUsername(value)
      .then(user => {
        const { id, username, email } = user;
        return findAddressByUserId(id);
      })
      .then(address => {
        return address;
      });`
      
    return findUserByUsername(value)
      .then(user => findAddressByUserId(user.id))
      .catch(e => {
        error = e.message;
      });
  }

async/await

  • Syntatic sugar라고도 하고 Promise를 그냥 적으면 직관적이지 않기에 async/await으로 동기처럼 개발자 친화적이게 해줌.
  • Promise를 활용한 비동기 코드를 간결하게 작성하는 문법.
  • async/await 문법으로 비동기 코드를 동기 코드처럼 간결하게 작성할 수 있다.
  • async 함수와 await 키워드를 이용한다.
  • await 키워드는 반드시 async 함수 안에서만 사용해야한다.
  • async로 선언된 함수는 반드시 Promise를 리턴한다.

async 함수

async function asyncFunc(){
	let data = await fetchData()
    let user = await fetchUser(data)
    return user
}   
  • async 함수는 function 키워드 앞에 async를 붙여 만든다.
  • async 함수 내부에서 await 키워드를 사용한다.
  • fetchData, fetchUser는 Promise를 리턴하는 함수이다.

await 키워드 실행 순서

async function asyncFunc(){
	let data1 = await fetchData1()
    let data2 = await fetchData2(data1)
    let data3 = await fetchData3(data2)
    return data3
}

function promiseFunc(){
	return fetchData1()
    	.then(fetchData2)
        .then(fetchData3)
}
  • await 키워드는, then 메서드 체인을 연결한 것처럼 순서대로 동작한다.
  • 비동기 코드에 쉽게 순서를 부여한다.

error 처리

async function asyncFunc(){
	try{
    	let data1 = await fetchData1()
        return fetchData2(data1)
    } catch(e) {
    	console.log("실패 :", e)
    }
}       
  • try-catch 구문으로 async/await 형태 비동기 코드 에러 처리가 가능하다.
  • catch 절의 e는, Promise의 catch 메서드가 받는 반환값과 동일하다. 즉, 한큐에 묶어서 처리가 가능하다.

정리

  • await 키워드로 비동기 처리에 순서를 부여한다.
    await 키워드는 여러 개가 쓰였을 시 뒤쪽 코드를 Promise의 .then() 함수를 사용하는 것처럼 만들어, 비동기 처리에 순서를 부여합니다.
  • 에러가 발생했을 경우 try-catch 구문으로 에러를 처리할 수 있다.
    try-catch 구문으로 비동기 코드의 에러 또한 처리할 수 있습니다.
  • async 함수 내부의 코드 실행은 비동기적이다.
    async 함수는 동기적으로 보이지만 비동기적으로 실행됩니다. 단, 내부에서 await 키워드가 쓰이지 않았을 경우엔 Promise.resolve() 로 처리됩니다.
  • await 키워드는 프로미스를 리턴하지 않는 함수라도 사용할 수 있다. 단 이 경우 리턴한 데이터는 Promise.resolve()로 감싸집니다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글