Home > database >  VueJs Axios D3.js "Error: too late; already running"
VueJs Axios D3.js "Error: too late; already running"

Time:08-22

I am trying to visualize some data with Vue-d3-charts. I am getting the data asyncronously with axios. The problem is that i am having issues with pushing the response data to the chart_data. Either i get the error that my variable(buildingdata) with the response is undefined (probably because the response arrives later than everything else and therefore ) or Error in callback for watcher "datum": "Error: too late; already running. Now i have confirmed that i am indeed getting a valid response by console logging the response to my browser. What am i doing wrong?

Here is the vue code in my component

<template lang="pug">
div
  .card
    .card-body
      //here is where the D3 component is 
      <D3BarChart :config="chart_config" :datum="chart_data" :title="chart_title"></D3BarChart>
</template>

<script>
import { D3BarChart } from 'vue-d3-charts';
import axios from "axios;
export default {
  components: {
    D3BarChart,
  },
  created(){
    console.log("created function ran")
    const sendGetRequest = async () => {
      try {
        let response = await axios.get("path_to_endpoint");
        let buildingdata = response.data;
        console.log(buildingdata)
        //the code runs fine until i get here and try to push the response data to the chart_data. 
        this.chart_data.push(...buildingdata)
      }
      catch (error) {
        console.log(error);
      }
    };
    sendGetRequest();

  },
  data() {
    console.log("data setup ran")
    return {
      chart_title: "Title",
      // Chart data, this is where D3 gets its data from.
      chart_data: [

      ],
      // This is the chart config. it is from here you can change the chart type, colors, etc.
      chart_config: {
        key: 'name',
        values: ['value'],
        orientation: 'vertical',
      },
    }
  },
}

</script>

Here is the output from my browser console

App mounted App.vue:35
data setup ran building.vue:36
created function ran building.vue:20
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html vue.esm.js:9132
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
[Vue warn]: Error in callback for watcher "datum": "Error: too late; already running"

found in

---> <D3BarChart>
       <OpenWoPerBuilding> at app/javascript/apps/new_insights/components/open_wo_per_building.vue
         <App> at app/javascript/apps/new_insights/App.vue
           <Root> vue.esm.js:628
    VueJS 15
    _callee$ open_wo_per_building.vue:26
    tryCatch app.js:221
    _invoke app.js:221
    defineIteratorMethods app.js:221
    asyncGeneratorStep app.js:235
    _next app.js:237
    (Async: promise callback)
    asyncGeneratorStep app.js:235
    _next app.js:237
    _asyncToGenerator app.js:237
    _asyncToGenerator app.js:237
    sendGetRequest open_wo_per_building.vue:21
    created open_wo_per_building.vue:32
    VueJS 41
    js app.js:12
    (Async: EventListener.handleEvent)
    js app.js:9
    Webpack 7
Error: too late; already running
    set schedule.js:42
    tweenFunction tween.js:31
    __WEBPACK_DEFAULT_EXPORT__ each.js:5
    __WEBPACK_DEFAULT_EXPORT__ tween.js:67
    __WEBPACK_DEFAULT_EXPORT__ attrTween.js:43
    __WEBPACK_DEFAULT_EXPORT__ attr.js:74

CodePudding user response:

So @kissu got me on the right track with the conditional rendering tip. What i did was use a flag that with a default of false in the "data()" that returns true after data has been fetched from axios in "created()".

<template lang="pug">
div(v-if="loaded")
  .card
    .card-body
        <D3BarChart :config="chart_config" :loaded="loaded" :datum="chart_data" :title="chart_title"></D3BarChart>
</template>

<script>
import { D3BarChart } from 'vue-d3-charts';
import axios from "axios";
export default {
  components: {
    D3BarChart,
  },
  created(){
    const sendGetRequest = async () => {
      try {
        let response = await axios.get("path_to_endpoint");
        let buildingdata = response.data;
        this.chart_data.push(...buildingdata)
        this.loaded=true
      }
      catch (error) {
        console.log(error);
      }
    };
    sendGetRequest();
  },
  data() {
    return {
      loaded: false,
      chart_title: "Title",
      chart_data: [],
      chart_config: {
        key: 'name',
        values: ['value'],
        color: {name: '#7f3727'},
        orientation: 'vertical',
      },
    }
  },
}

</script>

CodePudding user response:

You need to wait to have some data before displaying your component. The reason being that the template is synchronous and is not waiting for your data to be fetched.

This can be solved with a small v-if expecting your data to be fetched.

<D3BarChart v-if="asyncDataDoneLoading"
  :config="chart_config"
  :loaded="loaded"
  :datum="chart_data"
  :title="chart_title">
</D3BarChart>
  • Related