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

react, nextjs 로 firebase 연동중에 궁금한 부분이 있어 문의 드립니다. 

 

기초가 부족하니 부족한 부분이 많네요.

 

Copy
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을 하면 정상적으로 실행이 됩니다. 

이 부분을 처리하려면 어떻게 해야할까요? 

조언을 구해도 될까요? 

 

고맙습니다. 

 

Copy
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개

채택된 답변
+20 포인트

비동기 함수 문제이고

이런 상황에서 setTimeout 으로 임의 딜레이를 주는것은 더 알수없는 사이드이펙트를 낳을수 있습니다.

해당 딜레이는 사용자 환경에 따라 1초안에 끝날수도 있지만 10초를 넘길수도 있습니다.

 

다음과 같은 부분이 보이는데

Copy
// const imgThumbUrl = await

하시려던것 처럼 await 키워드로 처리 하거나

 

Promise 객체를 이용해 묶음처리 해주어야 합니다.

예제 올려드리니 응용해보시기 바랍니다.

그리고 예제에는 resolve 처리에 대한 부분만 있지만

실제는 reject 가 발생할 수도 있기 때문에 예외처리도 작업하셔야 할겁니다.

Copy
<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>
로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

답변 주셔서 고맙습니다. 참고해서 해결하겠습니다. 즐거운 하루 되세요!!

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인
🐛 버그신고