Promise / Async & Await 21.04.02


  • promise : 자바스크립트 비동기 처리에 사용되는 객체

  • 비동기 처리 : 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행

  • Promise 생성

const amICool = new Promise((resolv, rejec) => {});

console.log(amICool);
// Promise {<pending>}

// Promise를 resolve해야 값을 나타내고 Promise를 끝낼 수 있다.
  • Promise + resolve
const amICool = new Promise((resolv, rejec) => {
    // setTimeout(() => {
    //     resolv("Yes You are!");
    // }, 3000)
    // 위 코드는 아래와 같이 변경 가능
    setTimeout(resolv, 3000, "Yes You are!");
});

console.log(amICool);

setInterval(console.log, 1000, amICool);

// setInterval 때문에 1초마다 실행
// Promise {<pending>} 
// Promise {<pending>}
// Promise {<pending>}

// Promise의 resolve가 3초 뒤에 실행 되므로 4번째 부터는 값이 출력
// Promise {<fulfilled>: "Yes You are!"}
// Promise {<fulfilled>: "Yes You are!"}
// Promise {<fulfilled>: "Yes You are!"}
// ... 무한 반복
// Promise {<fulfilled>: "Yes You are!"} 


  • promise + Then : promise가 끝난 이후의 명령어를 전달
// then + arguments인 value로 불러오기
const amICool = new Promise((resolv, rejec) => {
    resolv("Yes you are!");
});

// Promise로 선언한 amIcool이 끝난 후 then 다음 함수 실행
amICool.then(value => console.log(value));
// Yes You are!

// 위 코드를 함수에 할당하여 then + function으로 불러오기
const thenFuntion = value => console.log(value);

amICool.then(thenFuntion);
// Yes You are!
  • reject : promise에 오류가 있는 경우 사용
const amICool = new Promise((resolv, rejec) => {
    setTimeout(rejec, 3000, "nope");
});

amICool.then(value => console.log(value));
// Promise {<pending>}
// 3초 후
// Uncaught (in promise) nope
// 에러를 확인하지 못해서 위와 같은 오류 코드 나옴
  • reject를 catch와 함께 사용하면 에러 값을 받을 수 있음.
const amICool = new Promise((resolv, rejec) => {
    setTimeout(rejec, 3000, "nope");
});

amICool
    // Promise가 resolve 되면 then 이후의 코드가 실행
    .then(result => console.log(result))
    // Promise가 reject 되면 catch 이후 코드가 실행
    .catch(error => console.log(error));
// Promise {<pending>}
// nope // 에러 코드 출력 메시지이다. 에러가 없다는 뜻.

Promise가 resolve 되면 then 이후의 코드가 실행

Promise가 reject 되면 catch 이후 코드가 실행

  • chaning Promise
// two에 promise 할당
const two = new Promise((resolv, rejec) => {
    // resolve되면 2 할당
    resolv(2);
});

// 2를 곱해주는 함수
const timesTwo = number => number * 2;

// Promise로 선언한 two에 .then(함수)를 붙여 연속 실행

two // two의 값은 resolve 되어 2
    .then(timesTwo) // 함수 실행 4
    .then(timesTwo) // 함수 실행 8
    .then(timesTwo) // 함수 실행 16
    .then(timesTwo) // 함수 실행 32
    .then(result => console.log(result)); // 결과 출력.
// 32
  • Promise.all

다수의 Promise를 한번에 실행. 즉, Promise.all은 다른 Promise들이 전부 진행 될 때까지 기다렸다가 실행된다.

모든 Promise가 전무 Resolve되면 마지막 Promise를 return value로 준다.

let promise1 = new Promise ((resolv) => {
    // resolve 되면 3초 후에 "First"
    setTimeout(resolv, 3000, "First");
})

let promise2 = new Promise ((resolv) => {
    // resolve 되면 1초 후에 "Second"
    setTimeout(resolv, 1000, "Second");
})

let promise3 = new Promise ((resolv) => {
    // resolve 되면 2초 후에 "Third"
    setTimeout(resolv, 2000, "Third");
})

// Promise.all로 불러오는 promise들은 반드시 iterable에 넣어줘야한다.
// Array와 같이 순회 가능한(iterable) 객체에 넣어줘야한다.
const alllPromise = Promise.all([promise1, promise2, promise3]);

alllPromise.then(values => console.log(values));
// Promise {<pending>}
// ["First", "Second", "Third"]
// promise1~3이 각각 언제 끝나는지 상관 없이 입력한 순서대로 출력된다.
  • Promise.all에 reject가 있는 경우 : 하나의 Promise라도 reject 되면 다른 모든 Promise도 reject
const promise1 = new Promise((resolv) => {
    setTimeout(resolv, 3000, "1");
})

const promise2 = new Promise((resolv, rejec) => {
    setTimeout(rejec, 1000, "에러에러에렁2");
})

const promise3 = new Promise((resolv) => {
    setTimeout(resolv, 2000, "3");
})

const alllPromise = Promise.all([promise1, promise2, promise3]);

// promise2가 아닌 allPromise에 .catch 추가 가능.
// 개별 Promise에 .catch를 넣을 수 있지만 한번에 표시하는 게 가독성도 좋고 코드도 간결해짐
alllPromise.then(result => console.log(result)).catch(err => console.log(err));
// 에러에러에렁2
  • Promise.race resolv로 나온 value든, catch로 나온 error든 가장 빨리 실행된 것만 실행 (race 경주로 생각하면 쉬움. 자주 사용하지는 않음)
const promise1 = new Promise(resolv => {
    setTimeout(resolv, 3000, "First");
});

const promise2 = new Promise(rejec => {
    setTimeout(rejec, 1000, "에렁");
});

const promise3 = new Promise(resolv => {
    setTimeout(resolv, 2000, "Third");
});

const promiseRace = Promise.race([promise1, promise2, promise3]);

promiseRace.then(v => console.log(v)).catch(e => console.log(e));
// Promise {<pending>}
// 에렁

const promise1 = new Promise(resolv => {
    setTimeout(resolv, 1000, "First");
});

const promise2 = new Promise(rejec => {
    setTimeout(rejec, 3000, "에렁");
});

const promise3 = new Promise(resolv => {
    setTimeout(resolv, 2000, "Third");
});

Promise.race([promise1, promise2, promise3]).then(v => console.log(v)).catch(e => console.log(e));
// First
  • Pormise Finally Promise에서 resolve 또는 reject 값을 실행하고 resolve되던 rejec되던 finally 함수 실행 (보통 API 호출 시 사용)
const promise1 = new Promise((resolv, rejec) => {
    setTimeout(resolv, 1000, "First");
}).then(v => console.log(v)).catch(e => console.log(e)).finally(() => console.log("Finally"));
// First
// Finally

const promise2 = new Promise((resolv, rejec) => {
    setTimeout(rejec, 1000, "에렁");
}).then(v => console.log(v)).catch(e => console.log(e)).finally(() => console.log("Finally"));
// 에렁
// Finally
Promise usecase

fetch : Promise를 return한다. 뭔가를 가지고 올 때 사용. 보통 직접 Promise를 만들기보단 fetch를 사용하여 다른 사람이 만든 Promise를 사용한다.

fetch("https://google.com").then(response => console.log(response)).catch(e => console.log("에러 발생! : google.com은 fetch 할 수 없따"));
// VM1075:1 GET https://google.com/ net::ERR_FAILED
// google.com은 fetch 할 수 없따

async & await

2개 이상의 Promise 사용시 async & await를 사용하여 업데이트, 코드의 가독성을 높인다. async & await는 Promise 밖에서 값을 가져올 수 있는 방법이다.

Promised의 then과 catch는 구식(then을 사용하면 then(function)을 여러번 사용해야하고 코드의 가독성을 떨어뜨리기 때문)

await는 항상 async function 안에서만 사용 가능하다. 수많은 then을 대체 가능. await는 기본적으로 Promise가 끝날 때 까지 기다린다.

  • then / catch 사용 시
// 화살표 함수 표현식
let getMoviesPromise = () => {
    fetch("url 주소") // fetch로 url 주소 가져오기
    .then (respon => { // fetch가 완료된 다음 reponse이 정상적으로 완료되었으면
        console.log(respon); // response를 console에 표시하고
        return respon.json(); // response의 json화 하여 return 한다.
    })
    .then(json => console.log(json)) // json화 된걸 return 한다음 console에 표시한다.
    .catch(err = > console.log(err)) // 에러 발생시 에러를 console에 표시한다.
}

getMoviesPromise();

위 코드를 async / await를 사용해서 바꿔보자.

// 화살표 함수 표현식으로 async 함수 선언
let getMoviesAsync = async() => {
    // 시도
    try {
        // fetch로 url 주소 가져오기
        let respon = await fetch ('url 주소'); 
         // fetch로 url 주소를 가져올 때 까지 기다렸다가 성공적으로 가지고 오면
        //  .json() 화해준다.
        let json = await respon.json();
        console.log(json);
    } catch(err) { // 에러 발생 시
        console.log(err); // 에러 출력
    } finally { // 완료 시 (finally는 respon되던 error가 뜨던 상관 없이 출력.)
        console.log("finally"); // 완료 출력.
    }
};

getMoviesAsync();
  • Parallel async/await : 병렬(동시에 여러개) 실행
// getMoviesAsync async 화살표 함수 표현
const getMoviesAsync = async() => {
    // 시도
    try{ 
        // moviesResponse와 upcomingResponse 각 변수에
        // 각 각 다른 API를 fetch로 가져오기
        const [moviesResponse, upcomingResponse] = await Promise.all([
            fetch("https://yts.mx/api/v2/list_movies.json"),
            fetch("https://yts.mx/api/v2/list_upcoming.json")
        ]);
        // json 할당
        const [movies, upcoming] = await Promise.all([
            moviesResponse.json(),
            upcomingResponse.json()
        ]);
        console.log(movies, upcoming);
    } catch(e) {
        console.log(e);
    } finally {
        console.log("finally");
    }
};

getMoviesAsync();





© 2020.11. by creamer

Powered by CREAMer