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

매출이 오르면 내리는 수수료! 지금 수수료센터에서 전자결제(PG)수수료 비교견적 신청해 보세요!
리액트로 파이어베이스 연동중 실행 순서에 대해 ..

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

회원로그인

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