리액트로 파이어베이스 연동중 실행 순서에 대해 ..
본문
react, nextjs 로 firebase 연동중에 궁금한 부분이 있어 문의 드립니다.
기초가 부족하니 부족한 부분이 많네요.
const [title, setTitle] = useState('')
const [client, setClient] = useState('')
const [theday, setTheday] = useState('')
const [tech, setTech] = useState('')
const [url, setUrl] = useState('')
// const [imgs, setImgs] = useState({imgThumb:null, imgPC:null, imgMo:null })
const [imgThumb, setImgThumb] = useState(null)
const [imgPC, setImgPC] = useState(null)
const [imgMo, setImgMo] = useState(null)
const [content, setContent] = useState('')
const [tags, setTags] = useState('')
const [cat, setCat] = useState('')
const createProject = async () => {
if( imgThumb != null ) {
let randomName = uuid();
const imageRef = ref(storage, `project-images/${imgThumb.name + randomName}`);
uploadBytes(imageRef, imgThumb).then(()=> {
getDownloadURL(ref(storage, `project-images/${imgThumb.name + randomName}`)).then((url)=>{
setImgThumb(url)
})
});
}
if( imgPC != null ) {
let randomName1 = uuid();
const imageRef = ref(storage, `project-images/${imgPC.name + randomName1}`);
uploadBytes(imageRef, imgPC).then(()=> {
getDownloadURL(ref(storage, `project-images/${imgPC.name + randomName1}`)).then((url)=>{
setImgPC(url)
})
});
}
if( imgMo != null ) {
let randomName2 = uuid();
const imageRef = ref(storage, `project-images/${imgMo.name + randomName2}`);
uploadBytes(imageRef, imgMo).then(()=> {
getDownloadURL(ref(storage, `project-images/${imgMo.name + randomName2}`)).then((url)=>{
setImgMo(url)
})
});
}
// const imgThumbUrl = await
//글 등록전 data 세팅
const data = {
title: title,
client: client,
completedDay: theday,
tech: tech,
url: url,
imgThumb: imgThumb,
imgPC: imgPC,
imgMo: imgMo,
content: content,
tags: tags,
cat: cat,
author: {name: auth.currentUser.displayName, id: auth.currentUser.uid }
}
console.log( data )
//글등록 실행
try {
const docRef = await addDoc(collection(db, "projects"), data);
console.log("다음 id로 document가 생성: ", docRef.id);
} catch (e) {
console.error(e);
}
}
위는 코드 중 일부분입니다. 파이어베이스에 글을 등록하려합니다.
문제 되는 부분은,
글등록 전,
const data = {} 값 세팅하는 부분인데요..
바로 위 if절 3개에서 값이 계산된 값 후, 그 값을 data에 적용하나 후,
try {
const docRef = await addDoc(collection(db, "projects"), data);
console.log("다음 id로 document가 생성: ", docRef.id);
}
가 진행이 되어야 하는데, 현재는, 바로 data 에 값이 저장되고 있습니다.
그로 인해 오류가 생기네요.
아래처럼 이 부분을 setTimeout을 하면 정상적으로 실행이 됩니다.
이 부분을 처리하려면 어떻게 해야할까요?
조언을 구해도 될까요?
고맙습니다.
setTimeout(function(){
const data = {
title: title,
client: client,
completedDay: theday,
tech: tech,
url: url,
imgThumb: imgThumb,
imgPC: imgPC,
imgMo: imgMo,
content: content,
tags: tags,
cat: cat,
author: {name: auth.currentUser.displayName, id: auth.currentUser.uid }
}
console.log( data )
}, 1000)
답변 1
비동기 함수 문제이고
이런 상황에서 setTimeout 으로 임의 딜레이를 주는것은 더 알수없는 사이드이펙트를 낳을수 있습니다.
해당 딜레이는 사용자 환경에 따라 1초안에 끝날수도 있지만 10초를 넘길수도 있습니다.
다음과 같은 부분이 보이는데
// const imgThumbUrl = await
하시려던것 처럼 await 키워드로 처리 하거나
Promise 객체를 이용해 묶음처리 해주어야 합니다.
예제 올려드리니 응용해보시기 바랍니다.
그리고 예제에는 resolve 처리에 대한 부분만 있지만
실제는 reject 가 발생할 수도 있기 때문에 예외처리도 작업하셔야 할겁니다.
<script>
async function fn_a(args) {
if (args.a == null) {
// return Promise.reject(null);
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
const t = 1000;
setTimeout(() => {
resolve(t);
}, t);
});
}
async function fn_b(args) {
if (args.b == null) {
// return Promise.reject(null);
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
const t = 2000;
setTimeout(() => {
resolve(t);
}, t);
});
}
async function fn_c(args) {
if (args.c == null) {
// return Promise.reject(null);
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
const t = 3000;
setTimeout(() => {
resolve(t);
}, t);
});
}
const createProject = async () => {
const param = {
a: 1,
b: null,
c: 3,
};
try {
fn_a(param);
fn_b(param);
fn_c(param);
const data = {
a: param.a,
b: param.b,
c: param.c,
};
console.log(JSON.stringify(data));
} catch (err) {
console.error(err);
}
};
const createProjectA = async () => {
const param = {
a: 1,
b: null,
c: 3,
};
const fn_set = [];
fn_set.push(fn_a(param));
fn_set.push(fn_b(param));
fn_set.push(fn_c(param));
const data = {
a: param.a,
b: param.b,
c: param.c,
};
Promise.all(fn_set).then((values) => {
[data.a, data.b, data.c] = values;
console.log(JSON.stringify(data));
}).catch(err => {
console.error(err);
});
};
createProject(); // {"a":1,"b":null,"c":3}
createProjectA(); // {"a":1000,"b":null,"c":3000}
</script>