모브박스 - 유튜브 api / then, async-await, setTimeout
const YOUTUBE_API_KEY = 'AAAAAAAAAAA';
let [youtubeId, setYoutubeId] = useState([]);
const youtubeMv = dailyBoxOffice.slice(0, 3);
// youtubeMv = ['베테랑2', '트랜스포머 ONE', '사랑의 하츄핑'];
useEffect(() => {
dataFetch4(dailyBoxOffice, movieDate)
youtubeMv.forEach((movie) => {
axios.get(
`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q=${movie} 예고편&type=video&key=${YOUTUBE_API_KEY}`
)
.then((res) => {
setYoutubeId(res.data.items);
})
.catch((err) => {
console.error(`Error fetching trailer for ${movie}: `, err);
});
})
}, [dailyBoxOffice])
console.log('youtubeId 검색결과', youtubeId);
console.log('youtubeId 검색결과', youtubeId);
'youtubeId 검색결과',[{..}]
'youtubeId 검색결과',[{..}]
'youtubeId 검색결과',[{..}]
youtubeId 값이 다 따로따로 나온다.
그러니 youtubeId.map을 해도 li는 하나만 출력된다.
<ul>
{
youtubeId.map((obj, index)=>(
<li k={index}>
<Link className="view_box" href={`https://www.youtube.com/watch?v=${obj.id.videoId}`} target="_blank">
<div className="thumb_box">
<Image src={obj.snippet.thumbnails.medium.url}
width={320} height={180}
alt="트레일러 썸네일" priority />
</div>
</Link>
</li>
))
}
비동기 작업 then 과 async/await 차이
then
async / await
동기(synchronous)란,
어떤 작업을 실행할 때 그 작업이 끝나기를 기다리는 방식
비동기(asynchronous)란,
어떤 작업을 실행할 때 그 작업이 완료되지 않더라도
다음 코드를 실행하는 방식을 의미한다.
(async와 await를 사용하면 비동기 코드를 동기 코드처럼 작성할 수 있어, 가독성이 좋아지고 에러 처리가 간단해진다.
ex.
function ziyeon() {
for (let i = 0; i < 10000; i++) {
console.log(1);
}
console.log(2);
}
동기 코드는 가장 먼저 바로 실행된다.
콘솔에 2가 찍히려면 1만 번의 1이 찍힐 때까지 기다려야 한다.
출처: https://trustmitt.tistory.com/85 [kohigowild:티스토리]
ex.
function ziyeon() {
for (let i = 0; i < 10000; i++) {
setTimeout(() => {
console.log(1); // 비동기처리
}, 0);
}
console.log(2);
}
ziyeon();
setTimeout 을 사용하여 콘솔 2먼저 찍히고 콘솔 1이 나중에 찍힌다.
즉, for루프가 도는동안 setTimeout은 비동기처리 된다.
function ziyeon() {
new Promise((resolve, reject) => {
try {
for (let i = 0; i < 10000; i++) {
console.log(1);
}
resolve();
} catch (error) {
reject('작업 실패!');
}
})
.then(() => {
console.log(2); // 비동기처리
})
.catch((error) => {
console.error(error);
});
}
ziyeon();
비동기 처리시 사용되는 메서드 new Promise()
인자값으로는 resolve/성공, reject/실패
try, catch 블럭으로 에러를 감지하고
for 루프가 문제없이 성공한다면 resolve() 호출하고,
비동기처리된 .then()이 실행한다.
작업 실패시 reject() 호출하여 .catch()가 실행한다.
async function ziyeon() {
console.log('1');
await new Promise((resolve) => setTimeout(resolve, 0));
console.log('3'); // 비동기
}
ziyeon();
console.log('2');
await는 반드시 async 함수 내부에서만 사용해야 한다.
콘솔1은 동기처리로 인해 바로 실행된다.
await로 인해 setTimeout()로 비동기처리 된 콘솔3은 실행대기하는동안
콘솔2 먼저 동기처리 되어 실행되고, 후에 콘솔3이 실행한다.
*여기서 0은 '0초 후 실행'이 아닌 다음 이벤트 루트로 코드를 미루는것임
useEffect(() => {
dataFetch4(dailyBoxOffice, movieDate)
const fetchYoutubeTrailers = async () => {
try {
const promises = youtubeMv.map((movie) =>
axios.get(
`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q=${movie} 예고편&type=video&key=${YOUTUBE_API_KEY}`
)
);
const responses = await Promise.all(promises); //모든 요청 기다림
const videoId = responses.map((response) => response.data.items[0]);
setYoutubeId(videoId);
console.log(videoId, 'videoId')
} catch (error) {
console.error('Error fetching YouTube trailers:', error);
}
};
fetchYoutubeTrailers();
}, [dailyBoxOffice])
console.log('youtubeId 검색결과', youtubeId);
fetchYoutubeTrailers 함수를 async로 비동기처리를 걸어놓고
promises에 영화에 대한 axios 요청 배열 생성하고
await로 axios의 실행이 완료 될때까지 기다린다.
만약 1개라도 실행이 안됐다면 catch 에러 블록으로 넘어간다.