[ vue.js ] forEach문에서 store.dispatch를 통한 API 통신 시 에러 문제점

조회수 271회

제목과 같이 vue.js 언어를 통해 외부 API를 호출하는 기능을 개발 중입니다.

개발하다보니 아래와 같은 동작을 구현해야 되는데 forEach문 안에서 API를 호출 요청하니 에러가 자꾸 발생되어 문의드립니다...

[ 흐름도 ]
1) API-1 호출 (return값: array) 
2) 받은 array 값을 forEach문 실행
3) array값에 있는 정보를 파라미터로 API-2 호출

에러메시지는 아래와 같습니다..

JsonToExcelAll > catch :  TypeError: **Cannot read properties of undefined (reading '$store')**
    at eval (d:\3.0\src\components\SideListContentsTable.vue?c027:697:1)
    at Array.forEach (<anonymous>)
    at eval (webpack-internal:///849:694:18) {stack: 'TypeError: Cannot read properties of undefine…
    at eval (webpack-internal:///849:694:18)', message: 'Cannot read properties of undefined (reading '$store')'}

forEach문 밖에서 API-2를 호출하면 정상작동합니다... 왜 이런것인지 답변 좀 부탁드리겠습니다...ㅠㅠ

[ 소스 추가 ]

parseJsonToExcel2(getTabInfo, getDongInfo) { // 엑셀 다운로드 함수

const self = this
this.json_to_excel = []

this.$store.dispatch('postSystemInfo', {  // API-1
        header: {
          cmd: '1'
        }
      }).then((data) => {

        if (data.result.status == '000' && data.header.cmd == '2') {

          _.forEach(_.orderBy(data.data.list, ['dong', 'ho'], ['asc', 'asc']), function (dong, i) { 

            arr_dong.push(dong) // 동 정보 array에 담음

          })

          // for문 안에서 array 값의 동 정보를 그대로 store 이용하여 파라미터 던지고 싶음
          // API-2를 여기 안에서 호출 시 에러...
          arr_dong.forEach(function (value, index) { 
            // console.log('TEST ====>> dong : ', value + " / i : " + index)
          })

          this.$store.dispatch('postDeviceStatus', { // API-2
            header: { cmd: '1' }, data: { dong: arr_dong[0], floor: 'all', line: 'all' }
          }).then((data) => {

            _.forEach(_.orderBy(data.data.data.list, ['dong', 'ho'], ['asc', 'asc']), function (data, pos) {

              getDong = data.dong
              getHo = data.ho
              getComm = data.comm

              _.forEach(_.orderBy(data.devices, ['uid'], ['asc']), function (v) {

                let json = {
                  '통신상태': getComm,
                  '기기ID': v.uid,
                  '기기상태': v.status,
                }

                self.json_to_excel.push(json)

              })

            })

            if (!_.isEmpty(this.json_to_excel)) {
              var worksheetByJson = XLSX.utils.json_to_sheet(this.json_to_excel);
              var book = XLSX.utils.book_new();
              XLSX.utils.book_append_sheet(book, worksheetByJson, getDong + "동");
              XLSX.writeFile(book, '상세_' + moment().format('YYYYMMDDHHmmss') + '.xlsx');
            }

          })

        } else {
          self.$store.commit('setAlertActive', { flag: true, msg: data.result.message })
        }

      }).catch((e) => {
        console.log('JsonToExcelAll > catch : ', e)
      })
  • API 1의 응답데이터는 $store 프로퍼티가 있는 자료형인가요? 오류도 좋지만 코드도 좀 올려주세요. 엽토군 2022.11.17 14:01
  • 위에 소스 추가했습니다...for문 안에서 store 호출도 안되고, json_to_excel 변수 참조도 바깥에서 호출하니 찾질 못해서 에러나네요... ssangyongtt@gmail.com 2022.11.17 16:30
  • API-2를 반복문 안에서 호출하면 에러가 발생한다는데, 그 문제의 코드가 없는 것 같습니다만 편집요청빌런 2022.11.18 11:13
  • 위에 소스에서는 API-2 부분을 for문 바깥으로 빼놓은 상태입니다... API-2 위에 있는 arr_dong.forEach... 안에 넣고 돌렸을 경우에 문제가 발생되고 있어요.. ssangyongtt@gmail.com 2022.11.18 11:21

1 답변

  • 좋아요

    1

    싫어요
    채택 취소하기
    arr_dong.forEach(function (value, index) { 
      // 여기
    })
    
    // API-2
    this.$store.dispatch('postDeviceStatus', {
      header: { cmd: '1' }, data: { dong: arr_dong[0], floor: 'all', line: 'all' }
    }).then((data) => {
    

    API-2에서 this를 참조하고 있는데, 이 코드를 그대로 여기에 넣어버리면 this가 가리키는 게 달라져서 발생하는 단순한 참조 에러입니다. 함수 내에서 this는 해당 함수를 소유한 객체가 되기 때문입니다.

    쉽게 말해서:

    arr_dong.forEach(function (value, index) { 
      this.$store.dispatch('postDeviceStatus', { // API-2
        header: { cmd: '1' }, data: { dong: arr_dong[0], floor: 'all', line: 'all' }
      })... // 생략
    })
    

    Array.forEach()에 제공한 함수가 익명함수이므로 this는 브라우저의 전역 객체인 window가 됩니다. 익명함수는 자바스크립트 실행체의 전역 객체가 소유하거든요. 그리고 window$store라는게 없겠죠?

    예외가 있는데 화살표 함수를 사용하면 this의 스코프가 달라지지 않습니다. 아래 예시를 참고하세요.

    let obj = {
      executeMe() {
        setTimeout(function() {
          console.log('function this:', this);
        }, 100);
    
        setTimeout(() => {
          console.log('arrow this', this);
        }, 100);
      }
    };
    
    obj.executeMe();
    // function this: Window ...
    // arrow this: Object ...
    
    • 완전 해결되었습니다...상세한 답변 감사합니다!! ssangyongtt@gmail.com 2022.11.21 14:52

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

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)