리액트로 파이어베이스 연동중 실행 순서에 대해 ..

리액트로 파이어베이스 연동중 실행 순서에 대해 ..

QA

리액트로 파이어베이스 연동중 실행 순서에 대해 ..

본문

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>
답변을 작성하시기 전에 로그인 해주세요.
전체 8
QA 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT