0

I'm creating a dynamic array in the computed: part of my .vue file. This array has a set of urls I each want to call (in a repeated component), to get articles. These articles vary, so on page render the computed array is made, and when that's done I want to call the urls the moment my component is made.

computed: {
    calcTheArray() {
        // make the actual array
        // basically, I grab a (computed! so can't use that in async either) 
        // array with months that have passed before today
        // I create an array with combined urls, that incorporate those month names
        // no other dependencies exist
        return array;
    }
}, 

then:

async asyncData({ error, app, }) {
    try {
        // lots of things happen here, another api call, some parsing etc.

        const promises = [];
        this.calcTheArray.forEach((value) => {
            promises.push(app.$axios.$get(`${value}`, { useCache: true }));
        });
    } catch (e) {
        console.log(e);
        return error({ statusCode: 500, message: e.message });
    }
},

The error I'm getting is: Cannot read property 'calcTheArray' of undefined

And I sort of understand why that is, as the async function is... well asynchronous, so my data doesn't exist yet? I think? But then how would I go about getting the dynamically created urls into my axios call?

What I've tried so far, is seeing whether the this.calcTheArray was the culprit and trying different ways to use the calculated array (vm.calcTheArray, just calcTheArray for example) I've also tried to define my the array in the data() { part

data() {
    return {
      calcTheArray: [],
    };
  },

But then I (obviously) end up with a Duplicated key 'calcTheArray'.

I'm at a loss. Can anyone give me a pointer?

6
  • 1
    Assuming this is Nuxt, see nuxtjs.org/guide/async-data. Quote 'You do NOT have access of the component instance through this inside asyncData because it is called before initiating the component.'. Without knowing what calcTheArray depends on it is difficult to advise further. Commented Dec 3, 2019 at 15:53
  • Thanks! You're right, I'm using Nuxt. calcTheArray only depends on todays date (or its month to be more precise). For all past months from a starting point until this month, I have a different API call to make. I dynamically build those from an array of month names. That's pretty much all calcTheArray does. I now do understand I why I can't use the calcTheArray in the async, but it's still unclear to me what I should do instead to get the calls working... Commented Dec 3, 2019 at 15:57
  • 1
    Could you not move the code from calcTheArray into your asyncData function? Commented Dec 3, 2019 at 16:00
  • I just updated my code... the array I reference is also calculated... Commented Dec 3, 2019 at 16:01
  • 1
    So what are the ultimate dependencies of all the relevant computed properties? e.g. Do they depend on any props, etc.? Is there actually anything from the instance that you need or have you just used computed properties for convenience? Is there any reason these can't just be defined as normal JavaScript functions, totally separate from your Vue component options? Commented Dec 3, 2019 at 16:14

1 Answer 1

1

If I understand correctly you want to execute the async method only when the calcTheArray has actually some value computed and prevent the undefined error. You can use a watcher to trigger the async function in that case, you could try the following:

computed: {
    calcTheArray() {
        // your code to create the array;
        return array;
    }
},
watch: {
    calcTheArray() {
        // executed when there's any mutation detected by vue on calcTheArray;
        this.asyncData(object)
    }
},
methods: {
    async asyncData({ error, app, }) {
      try {
         // lots of things happen here, another api call, some parsing etc.

         const promises = [];
         this.calcTheArray.forEach((value) => {
            promises.push(app.$axios.$get(`${value}`, { useCache: true }));
         });
       } catch (e) {
         console.log(e);
         return error({ statusCode: 500, message: e.message });
       }
   }
}

This way, vue will wait to the computed array before start the async method. Hope it suits you well.

Sign up to request clarification or add additional context in comments.

1 Comment

This is looking really logical... For my situation, the actual watching isn't needed, as the articles will be loaded on page load, but I did gain some insights from your answer. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.