Open geeks-lab opened 10 months ago
이렇게 image를 그냥 리턴해주면 안됩니다. 맵에서 하나씩 돌면서 리턴하는 값은 image인데 async 라서 promise를 반환합니다. 따라서 promise.all로 감싸줘야합니다. 그러면 promise 배열을 리턴합니다. 각 promise는 이미지를 리턴합니다.
그리고 Promise.all 앞에 await 를 해주면 거의 병렬적으로 처리됩니다.
// server/routes/imageRouter.js
imageRouter.post("/", upload.array("image", 5), async (req, res) => {
try {
if (!req.user) throw new Error("권한이 없습니다.");
const images = await Promise.all(
req.files.map(async (file) => {
res.json();
const image = await new Image({
user: {
_id: req.user.id,
name: req.user.name,
username: req.user.username,
},
public: req.body.public,
key: file.filename,
originalFileName: file.originalname,
}).save();
return image;
})
);
res.json(images);
} catch (error) {
console.log(error);
res.status(400).json({ message: error.message });
}
});
for (let file of files)
여러개 올리는게 이제 가능하긴 한데 마지막 사진을 보면 정상적으로 보이지 않습니다.
if (isPublic) setImages([...images, ...res.data]);
이렇게 하고 테스트하니 에러가 해결되었습니다.현재는 여러개를 업로드하려고 선택해도 하나의 프리뷰만 보이기 때문에 선택한 이미지들 모두 프리뷰가 보일 수 있게 합니다.
이전에 썼던 코드 초록 부분을 보면 비동기 적으로 처리하고 있는 모습이다.(그래야 이미지가 업로드 되는 동안 다른 사진을 구경한다던지 유저가 다른 일을 할 수 있으니까) 그런데 지금 맵 안에서 감싸줬는데 비동기적으로 처리되니까 배열안에 하나의 사진만 들어가게 됩니다.
그보다, 한번 업로드 될 때 배열에 여러개의 사진을 한번에 올리고 싶기 때문에 여러개의 사진이 다 올라갈 때 까지 기다려줘야 합니다.(지난번에 back에서 비슷한 문제를 처리한 적이 있습니다!)
따라서 Promise.all로 감싸줍니다.
그렇지만 안의 코드가 promise 를 반환하지 않기 때문에 promise 를 직접 만들어 줘야 합니다.
const imageSelectHandler = async (event) => {
const imageFiles = event.target.files;
setFiles(imageFiles);
// 여러 이미지 보기
const imagePreviews = await Promise.all(
[...imageFiles].map(async (imageFile) => {
return new Promise((resolve, reject) => {
try {
const fileReader = new FileReader();
fileReader.readAsDataURL(imageFile);
fileReader.onload = (e) => resolve(e.target.result);
} catch (error) {
reject(error);
}
});
})
);
resolve(e.target.result);
-> resolve({ imgSrc: e.target.result, fileName: imageFile.name });
이 문법 쉽지 않다...
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
IntersectionObserver Intersection Observer API의 IntersectionObserver 인터페이스는 대상 요소와 상위 요소, 또는 대상 요소와 최상위 문서의 뷰포트가 서로 교차하는 영역이 달라지는 경우 이를 비동기적으로 감지할 수 있는 수단을 제공합니다.
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
entry.isIntersecting;
});
}, []);
ImageList 함수 내부의 useEffect 모습
useEffect(() => {
if (!elementRef.current) return;
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
loadMoreImages();
}
});
observer.observe(elementRef.current);
return () => observer.disconnect(); // when the mouse wheel goes up, the same observer
// is makeing the error sinsce they are calling the same images
}, [loadMoreImages]);