티스토리 뷰
목표
1. 버튼을 누르면 해당 하는 조건으로 데이터 정렬
2. 정렬된 데이터를 다른 페이지로 가져가서 뽑아내기
3. 기능들 함수화 시키기
이룬것
1. 버튼을 누르면 해당 하는 조건으로 데이터 정렬
• 버튼을 누르면 if문에서 조건을 판별 할 아이디 가져오기
- HTML의 요소에 id를 주고 addEventListener를 사용하여 버튼을 누르면 해당 아이디를 가져올수 있도록 구성하였습니다.
maintitle_Container.addEventListener('click', function (e) {
const buttonId = e.target.id;
}
- 이 버튼의 id값을 사용해서 미리 출력할 값들을 저장 및 정렬까지하고 페이지를 이동해서
출력만 하면 좋을것 같다고 생각하였습니다.
- 위 함수의 스코프 안에서 작업을 하는게 가장 복잡하지 않고 가독성이 좋을것이라 생각해
블럭안에서 작업을 하였습니다.
• if문을 진행할 api데이터 가져오기
< api를 가져와서 저장하기 위한 작업 >
Promise.all을 사용하게 된다면 하나의 거부가 나오면 전부다 거부처리 되므로 그 점을 개선하기 위해
Promise.allsettled를 사용해서 거부가 되더라도 이행할수 있도록 하였습니다.
// api를 가져오기 위한 fetch작업
const fetchData = async (urls) => {
const response = await fetch(urls, options);
const data = await response.json();
return data;
};
// 각 URL에 대해 fetchData 함수를 호출하고 결과를 기다림
const fetchPromises = urls.map(url => fetchData(url));
// 모든 Promise가 처리되도록 기다림
Promise.allSettled(fetchPromises)
.then(results => {
let newMovies = [];
// 값을 바로 꺼내기 위한 사전 작업
let movies = [results[0]['value']['results'], results[1]['value']['results']];
for(let i = 0; i < movies.length; i++){
for(let j = 0; j<movies[0].length; j++){
newMovies.push(movies[i][j]);
}
}
let sortedMovies = sortMovie(newMovies,buttonId) // 꺼내온 값을 정렬하기위한 함수 호출
makeCard(sortedMovies)
})
.catch(error => {
console.error(error);
});
■ Promise.all의 문제점
- Promise.all은 주어진 프로미스 중 하나가 거부하는 경우, 첫번째로 거절한 프로미스의 이유를 사용해 자신도 거부 합니다.
즉, 주어진 Promise 중하나라도 Reject되는 경우 모두 이행 취소가 되어버리는 것입니다.
이렇게 되면 잘 되는 작업도 하나라도 실패해 버리면 다 실패한 작업이 되어 버리는 것입니다.
- 하나의 예로 한번에 너무 많은 Request를 서버에 날리게 되면 서버에 과부하를 줄 수 있습니다.
■ Promise.allSettled() ( ES2020 추가 )
▢ 여러 프로미스를 병렬적으로 처리하지만, 하나의 프로미스가 실패해도 무조건 이행합니다.
▢ 다중의 Promise를 동시에 처리할수가 있고 이행 취소가 됐을 때 모든 작업이 거부된는 일이 발생하지 않습니다.
▢ 모든 Promise가 처리되면 결과를 배열로 반환하고 배열의 각 요소는 처리 상태와 해당 Promise의 결과 또는
rejection이유를 나타내는 객체로 구성되어 있습니다.
▢ 성공하면 status의 필드에 fulfilled(이행)값을 넣고, 실패하면 rejected(거부)값을 넣습니다.
▢ 배열을 순회해서 값을 얻을 수가 있습니다.
• if문에 진입한 아이디별로 각각의 조건 진행하기
- 주어진 문자열과 같은 id가 들어온다면 해당하는 정렬을 진행해줍니다.
- 숫자로 받아오는 평점과 인기도 순으로 정렬한다고 하면 b와 a를 비교하여 내림차순 구현을 하였습니다.
- 한글로 비교를 한다면 a와 b를 localeCompare로 비교를 하여 ㄱ,ㄴ,ㄷ순으로 오름차순 구현을 하였습니다.
- 위 정렬 과정이 끝나고 값을 반환 합니다.
function sortMovie(movies,buttonId){
if(buttonId == 'sortRatings'){
return movies.sort((a, b) => b['vote_average'] - a['vote_average']);
}else if(buttonId == 'sortTitle'){
return movies.sort((a, b) => a['title'].localeCompare(b['title']));
}else if(buttonId == 'sortpopular'){
return movies.sort((a, b) => b['popularity']-(a['popularity']));
}else if(buttonId == 'sortComming'){
return movies.sort((a, b) => b['release_date'].localeCompare(a['release_date']));
}
}
• 진행한 조건 전달.
- 카드를 만드는 함수를 불러와 방금 정렬한 데이터를 넣어줍니다.
makeCard(sortedMovies)
2. 정렬된 데이터를 다른 페이지로 가져가서 뽑아내기
• window.localStorage로 데이터 넣기.
- 다른 페이지로 넘어가서 사용하기 위해 해당하는 정보를 객체에 저장해 문자열 형태로 만들어 줍니다.
※ 문자열로 만들어주는 이유는 key : value에는 문자열 형태로 들어가야 하기 때문!
- 데이터를 출력하고 싶은 페이지로 이동합니다.
function makeCard(movies) {
const queryParams = new URLSearchParams();
// 배열 순회하며 값저장하기 위한 for문
for (let i = 0; i < movies.length; i++) {
//movie의 배열에 접근
let movie = movies[i]
// localStorage에 저장할 value값 생성
let movieInfo = {
title: `${movie['title']}`,
overview: `${movie['overview']}`,
vote_average: `${movie['vote_average']}`,
poster_path: `${movie['poster_path']}`,
popularity: `${movie['popularity']}`,
release_date: `${movie['release_date']}`
}
// 객체를 Json 문자열로 변환
let movieInfoString = JSON.stringify(movieInfo)
// localStorage에 해당하는 아이디 키값과 키값에 맞는 value값 저장
window.localStorage.setItem(`${movie['id']}`, movieInfoString)
queryParams.append('cardIds', movie['id']);
}
// 해당 페이지로 값을 가지고 이동
window.location.href = `../../index.html?${queryParams.toString()}`
}
• window.localStorage로 데이터 가져오기.
- localStorage에 저장된 Key값을 가져옵니다.
- Json.parse를 활용하여 localStorage에 저장된 Json형식의 문자열로 저장된 객체를 Js객체로 변환합니다.
- 가져온 데이터에서 필요한 정보만 가져와서 해당하는 화면에 띄어줍니다.
const card_list = document.querySelector('#card_list');
function readURLParameter(name) {
// location.search : 쿼리문자열 값 == naver.com?a=3 일때 ?a=3
const params = new URLSearchParams(window.location.search);
return params.getAll(name);
}
let baseImgUrl = 'https://image.tmdb.org/t/p/original'
const cardIds = readURLParameter('cardIds');
// cardIds가 있다면?진입
if (cardIds.length > 0) {
for (const cardId of cardIds) {
// 키 값을 가져 오기
const cardInfoString = window.localStorage.getItem(cardId);
// 키 값이 있다면? 진입
if (cardInfoString) {
const cardInfo = JSON.parse(cardInfoString);
const div = document.createElement("div");
div.className = "movie_card";
div.id = cardId;
div.style.width = '250px';
div.style.padding = '20px';
div.style.backgroundColor = 'rgb(233 69 69)';
div.innerHTML = `<img src="${baseImgUrl}${cardInfo.poster_path}" alt="이미지없음"></img>`;
card_list.appendChild(div);
}
}
}
개선할것
■ 함수처리는 여러 곳에서 사용하기위해 즉, 재활용하기 위한 기능들인텐데 한번밖에 쓰지 않았습니다.
이 부분에 함수를 쓰는게 맞는지에 대한? 의문이 있어 확신이 들 정도의 Fundamenta 공부를 해야 할것 같습니다.
■ 현재는 바닐라 자바스크립트로만 만들기 때문에 조금 비효율? 적인 방법을 쓰는데 다른 방법을 사용한다면
어떻게 진행되는지에 대한 방법을 모색해봐야 할것같습니다.
■ async / await 를 사용하지 않았습니다. 위 방법을 보면 다른 함수에서 데이터를 가져오고 그다음 작업들을 시행하는데
함수가 실행하고 다음 함수로 넘어가기 까지의 비동기 적인 동적방법을 써야 안전하지 않을까?
라는 생각이 들어 좀 보완해야 할것 같습니다.
■ localStorage에 key : value를 넣게 되면 순차적으로 들어가는 것이 아닌 무작위로 들어가서 정렬이 되어있지 않았습니다. 그 부분을 해결하기 위해 미리 정렬을 해주고 쿼리 문자열을 사용하기 위해 URLsearchParams를 사용하여 쿼리문에 정렬된 데이터를 넣고 전달을 해줬습니다. 그렇게 하면 생기는 문제가
정렬된 데이터의 cardId가 url에 적여서 나오는 문제가 있었습니다.
이렇게 되면 보안적인 부분에서도 문제가 생길것이 분명하므로 정렬을 미리하지말고
localStorage에서 값을 꺼내 오면서 정렬을 하는 방법을 찾고 보완해야 할 것 같습니다.
배워나가는 코린이 입니다!!
부족한게 있다면 댓글로 지적해주세요!! 감사합니다!😊
'project > sparta' 카테고리의 다른 글
[최종 프로젝트] Puppeteer 크롤링하기2<문자열 유사성 알고리즘> (0) | 2024.04.05 |
---|---|
[최종 프로젝트] Puppeteer 크롤링하기 1 (0) | 2024.04.03 |
[최종 프로젝트] 개발일정 논의 및 기술 결정 (0) | 2024.03.28 |
TIL 10일차 + fetch(), Promise.all() (1) | 2024.01.05 |
Cannot read properties of null (reading 'append') 에러 (0) | 2024.01.04 |