Search code examples
javascriptvue.jsasync-awaitfetchcomputed-properties

How to properly wait for fetched data in vue.js for proper usage in another method


How do i properly wait for the fetch to be successful so that executing the loadMarkers() method won't throw an error because monitorsData.monitors is undefined?

I tried it with using await in front of fetch but i don't really understand how to use it properly either.

data(){
        return{
            monitorsData:'',
            timer:'',
            loading:false,
            message:'60200950',
            markers: [],
        }
    },
    created(){
        this.searchStation()
        this.loadMarkers()
        this.timer = setInterval(this.searchStation, 50000)
    },
    methods:{
        loadMarkers(){
            for(let i = 0; i < this.monitorsData.monitors.length; i++){
                this.markers.push({id: i, position: {lat: this.monitorsData.monitors[i].locationStop.geometry.coordinates[0], lng: this.monitorsData.monitors[i].locationStop.geometry.coordinates[1]}})                  
            }
        },
        searchStation(){
            this.loading=true
            var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
                targetUrl = 'http://www.wienerlinien.at/ogd_realtime/monitor?DIVA='+ this.message+ '&activateTrafficInfo=stoerungkurz'
            fetch(proxyUrl + targetUrl)
            .then(response => response.json())
            .then(jsonData => this.monitorsData = jsonData.data)
            .catch(e => console.log(e))
            this.loading = false
            this.message = ''
        },

    },


Additionally i don't know how to prevent the same problem in computed

    computed:{
        mapConfig() {
            return{
                ...mapSettings,
                zoom: 8,
                center: {lat: this.monitorsData.monitors[0].locationStop.geometry.coordinates[0], lng: this.monitorsData.monitors[0].locationStop.geometry.coordinates[1]}
            }
        }
    },

Solution

  • Move your loading and message into your then chain

    searchStation(){
        this.loading=true
        var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
            targetUrl = 'http://www.wienerlinien.at/ogd_realtime/monitor?DIVA='+ this.message+ '&activateTrafficInfo=stoerungkurz'
        fetch(proxyUrl + targetUrl)
        .then(response => response.json())
        .then(jsonData => {
           this.monitorsData = jsonData.data
           this.loading = false
           this.message = ''
            })
        .catch(e => console.log(e))
    
    },
    

    Ok now you can use an if statement to check if its still loading:

        loadMarkers(){
            if(this.loading) return; //if its true, the function will stop here
            for(let i = 0; i < this.monitorsData.monitors.length; i++){
                this.markers.push({id: i, position: {lat: this.monitorsData.monitors[i].locationStop.geometry.coordinates[0], lng: this.monitorsData.monitors[i].locationStop.geometry.coordinates[1]}})                  
            }
        },
    

    Should work for your computed property too:

        mapConfig() {
            if(this.loading) return;
            return{
                ...mapSettings,
                zoom: 8,
                center: {lat: this.monitorsData.monitors[0].locationStop.geometry.coordinates[0], lng: this.monitorsData.monitors[0].locationStop.geometry.coordinates[1]}
            }
        }