Promise / Async & Await 21.04.02
in Dev on Java Script
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();