[React] Front-End

[FE] JS ES6 : 화살표 함수 / Promise / async / await / Promiss.all() / Promise.race()

ddgoori 2021. 7. 6. 21:55

 

Arrow Functuon 생략버전 확인

 

 

JavaScript - 화살표 함수(Arrow function)

화살표 함수는 ES6문법입니다. function 키워드 사용해서 함수를 만든 것보다 간단히 함수를 표현할 수 있습니다. 화살표 함수는 항상 익명입니다. 1. 화살표 함수의 기본문법 콜백 함수에서도 사용

velog.io

 

Promise 사용법

 

 

 

getHen()이 성공하면

getHen()을 통해 받아온 hen을 getEgg(hen)으로 매개변수로 넣고 실행

그 hen은 getHen에서 resolve(성공시 리턴하는 값) 🐓 임

getEgg(hen) 이행시 해당 함수가 성공시 리턴하는 값  🐓 => 🥚을 리턴하고

그 리턴된 egg를 cook(egg)로 매개변수로 넣어주고 완료시 🐓 => 🥚 => 🍳 이 리턴됨.

 

이리턴된 값은 meal을 매개변수로 넣고 이를 colsole.log(meal)로 출력한다. 

그렇다면 최종적으로 🐓 => 🥚 => 🍳  가 출력됨

pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태
fulfilled(완료): 비동기 처리가 완료되어 프로미스 결과 값을 반환해준 상태
rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태.

 

마지막 Promise Chaining에서는 아래와 같이 바꿔줄 수 있다. 

getHen()
   .then(hen => getEgg(hen)
   .then(egg => cook(egg)
   .then(finalMeal => console.log(finalMeal));

promise리턴값을 다음 promise에 그대로 대입하는 것이라면 아래 처럼 생략가능...

(이렇게 생략 가능한 문법 때문에 JS ES6 문법을 잘 모르면 더 헷갈림 ㅜㅜ)

 

마지막에 catch를 통해 에러를 잡아줄 수 있음

 

getEgg시에 문제가 생긴다면? 피자를 넣어줄게요! 

문제가 생긴 것 다음에 catch를 넣으면 됨.

 

getHen()
   .then(hen => getEgg(hen)
   .catch(error => {
   		return '🍕';
   })
   .then(egg => cook(egg)
   .then(finalMeal => console.log(finalMeal));

 

Promise를 사용하여 콜백지옥에서 벗어나는 법!

 

UserStorage //에서 로그인을 한다음에 (
   .loginUser(id, password) // 성공하면, 유저가 전달되어 다음 then이 실행됨
   .then(userStorage.getRoles)
   .then(user => alert(`${user.name}, you have a ${user.role} role`);
   .catch(console.log); //문제가 생기면 출력

 

 

Async 

 

깔끔하게 promise를 사용하는 방법이 async / await임

clear style of using promise

 

사용법

 

자바스크립트는 원래 동기적으로 실행된다. 아래의 예제코드를 보자.

위에서부터 아래로 순차적으로 코드가 실행된다. 이때 네트워크 처리가 10초가 걸리면

10초 후에 console.log(user); 가 실행될 것이고, 이후에 웹페이지 화면을 처리하는 로직이 있다면

사용자는 10초 동안 빈 화면을 보게될 것이다.

 

이때 비동기가 필요한 것임!

function fetchUser() {

	// do network request in 10 secs
    // 네트워크 처리 10초
    return 'dahae'
    
}

const user = fetchUser();
conole.log(user);

 

Promise를 사용하면 아래와 같이 사용됨.

비동기적으로 실행하여 끝나면 호출해줄게!

이때, 주의할 점은 resolve('dahae'); 처럼 resolve를 사용하지 않으면 PromiseState가 "fulfilled" 이 되지 않고 pending이 뜸

 

=> promise 안에서는 꼭 resolve나 reject로 처리를 해줘야한다!

 

function fetchUser() {
	// do network request in 10 secs
    // 네트워크 처리 10초
    
	return new Promise((resolve, reject) => {
        resolve('dahae');
    });
}

const user = fetchUser();
conole.log(user);

 

근데, Promise를 사용하지 않고도 비동기로 사용할 수가 있다!

함수 앞에 async를 붙여주면 됨

=> 함수 안에 있는 코드블럭이 자동으로 promise로 변환됨.

async function fetchUser() {
	// do network request in 10 secs
    // 네트워크 처리 10초
    
	return 'dahae';
}

const user = fetchUser();
conole.log(user);

 

 

 

 

Await

 

await이라는 키워드는 async라는 키워드가 붙은 함수 앞에서만 사용할 수 있다. 

정해진 ms이 지나면 resolove를 리턴하는 함수

function delay(ms) {
	return new Promise(resolve => setTimeout(resolve, ms));
}

// 3초가 지나면 resolve 받아와서 사과 리턴! 
async function getApple() {
	await delay(3000);
    
    return '🍎';
}

// delay가 끝날 때까지 기다려. 그리고 3초 있다가 바나나를 리턴!
async function getBanana() {
	await deley(3000);
    return '🍌';
}

// promise도 너무 중첩시키면 콜백지옥 같음
function pickFruites() {
	return getApple().then(apple => {
		return getBanana().then(banana => `${apple} + ${banana}`);    
    });
}

// async로 변환하기
async function pickFruits() {
	const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`;
}

// error 처리
async function pickFruits() {
	try {
    	const apple = await getApple();
    	const banana = await getBanana();
    } catch() {
   
   }
   return `${apple} + ${banana}`;
}

// 한가지 문제점
// 위의 코드에서 사과와 바나나를 받는 코드는 서로 연관이 되어있지 않다. 
// 근데 사과 받는데 1초 기다려, 바나나 받는데 1초 기다려 됨. 고쳐볼까?
// 병렬적으로 사과랑 바나나랑 1초만에 가능 (서로 상관이 없기 때문임)

async function pickFruits() {
	const applePromise = getApple();   //promise를 만드는 순간 프로미스 안에 있는 코드가 실행됨
    const bananaPromise = getBanan();   //마찬가지로 만드는순간 코드 바로 실행됨
	const apple = await applePromise();
    const banana = await bananaPromise();
    return `${apple} + ${banana}`;
}

// 더 간단한 api로 병렬 가능(서로 연관없는 api 호출시)
function pickAllFruites() {
  return Promise.all([getApple(), getBanana()]).then(fruits =>  //다 받아지면 출력됨
		fruits.join(' + ')
  );
}

pickFruites().then(console.log);


// promise 배열 중에 가장먼저 호출된 것 전달함

function pickOnlyOne() {
	return Promise.race([getApple(), getBanana()]);
}

pickOnlyOne().then(console.log); //바나나 먼저 전달됨

 

Promise.race()

Promise.race() 메소드는 Promise 객체를 반환합니다. 이 프로미스 객체는 iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부합니다.

 

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

 

 

=> 솔직히 실무에서 어떻게 써야할지 확 와닿지는 않는다..

 

Promise.all() / 자바스크립트 문법

 

Promise.all() - JavaScript | MDN

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다. 주어진 프로미스 중 하나가 거부하는 경우, 첫

developer.mozilla.org

 

Promise.race() - JavaScript | MDN

Promise.race() 메소드는 Promise 객체를 반환합니다. 이 프로미스 객체는 iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부합니다.

developer.mozilla.org

 

 

출처: 드림코딩 앨리 promise / 캡틴판교 자바스크립트 promise 쉽게 이해하기