Passing the response from axios in Vue to a separate method

I have a function that converts currency values like this:

    convertCurrency (recipe_line) {
      axios.get('https://api.exchangeratesapi.io/latest?base=' + recipe_line.currency_buy + '&symbols=' + this.currentLocation.currency)
      .then(response => {
         let rate = response.data.rates[Object.keys(response.data.rates)[0]]
         return rate
      })
    },

This conversion function is used within another function:

calculateTotalConverted (recipe_line) {
  let pricebuy = this.convertCurrency(recipe_line)
}

When I console.log(rate) in the first function, it displays the correct result.

But when I console.log(pricebuy) in the second function, it returns undefined.

How can I access the axios response in the second function?

Answer №1

converter (recipe_line) {
      axios.get('https://api.exchangeratesapi.io/latest?base=' + recipe_line.currency_buy + '&symbols=' + this.currentLocation.currency)
      .then(response => {
         let rate = response.data.rates[Object.keys(response.data.rates)[0]]
         return rate
      })
    },

To simplify and improve readability, you can utilize the async/await syntax in your code. This approach gives a more synchronous feel to asynchronous operations.

  async converter(recipe_line) {
    try {
      const response = await axiox.get(
        'https://api.exchangeratesapi.io/latest?base=' +
          recipe_line.currency_buy +
          '&symbols=' +
          this.currentLocation.currency
      );

      return response.data.rates[Object.keys(response.data.rates)[0]];
    } catch (error) {
      console.log(error);
    }
  }

An alternative implementation would be:

  converter(recipe_line) {
    axios
      .get(
        'https://api.exchangeratesapi.io/latest?base=' +
          recipe_line.currency_buy +
          '&symbols=' +
          this.currentLocation.currency
      )
      .then((response) => {
        let rate = response.data.rates[Object.keys(response.data.rates)[0]];
        Promise.resolve(rate);
      })
      .catch((err) => Promise.reject(err));
  }

The issue in your original code is that the promise isn't resolving properly. You need to use Promise.resolve() to ensure the return value is resolved within the promise.

With ES6's async/await syntax, you have a more synchronous way of handling asynchronous tasks, offering an easier-to-read alternative to traditional Promise chaining (.then/.catch).

Additionally, consider simplifying Object.keys(response.data.rates) to directly reference the key name for better clarity and efficiency.

For instance, if the key is "rate1", you could use response.data.rates['rate1'] instead.

Depending on your specific requirements, optimizing this part of the code may enhance its functionality.

Answer №2

There are a couple of issues in your code that need to be addressed.

  1. The first method is not returning anything, so you need to make sure to return the call to axios.get(/* ... */)
  2. You're attempting to retrieve a value immediately from an asynchronous operation, which will result in getting [object Promise] instead of undefined

One simple solution to this problem is to utilize async/await. However, if you intend to display this information in a view using VueJS, you'll need a data property as VueJS doesn't support awaiting asynchronous operations directly within templates.

I've modified your example slightly to work with a more straightforward API. Here's how you can achieve this:

var app = new Vue({
  el: "#app",
  data: {
    url: ""
  },
  async mounted() {
    this.url = await this.getUrl();
  },
  methods: {
    getCat() {
      return axios
        .get("https://api.thecatapi.com/v1/images/search")
        .then((response) => {
          return response.data[0].url;
        });
    },
    async getUrl() {
      let catImage = await this.getCat();
      console.log(catImage); // no longer undefined
      return catImage;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<div id="app">{{ url }}</div>

If you're already utilizing async/await, you can simplify your axios call by removing the promise and updating it like this:

    async getCat() {
      return (await axios("https://api.thecatapi.com/v1/images/search")).data[0].url;
    },

Update

You mentioned that you need to render this data in your template. It's important to note that trying to do something like this in VueJS won't work:

<div>{{ getUrl() }}</div>

VueJS cannot render an asynchronous function directly in a template. The output on the page would just be [object Promise]. When calling getUrl (an asynchronous function), you initially receive a Promise. Vue does not update the rendered content of an asynchronous function. Therefore, even after the Promise resolves with a result from axios, [object Promise] will still appear on the page.

Therefore, you have two options. You can update the value of one of your data properties based on the asynchronous action, or you can consider using a library that supports async computed properties such as: https://github.com/foxbenjaminfox/vue-async-computed

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When accessed through jQuery, the WebAPI Controller will route to a plain JSON view

I am encountering a strange issue with my ASP.NET MVC application. When calling a WebAPI controller through jQuery's $.get method, everything works fine until the callback function finishes. Instead of seeing my web page, I am redirected to a raw JSON ...

Is it possible to set up a server with 'app' as the designated request handler?

When working with NodeJS, server creation can be done simply by using: http.createServer(function(req,res) { /* header etc. */}); However, as I delved into using express, the server was automatically created for me. Moving on to learning about sockets, I ...

Passing a variable through jQuery onClick event to a URL via GET request and subsequently loading the content of

After successfully passing variables through AJAX calls via onClick to a PHP file and loading the results on the initial page, I now face the challenge of passing a variable analogously via onClick to a PHP file but this time I need to either open a new wi ...

Dynamically obtaining the screen width in JSP using a variable

Could someone provide assistance on how to resize an image using an img src="blah.jpg?width=x" so that my page can be displayed at various sizes? I just need x (width) as a JSP variable. Update 2021: It's been 9 years since this question wa ...

Pass the value of the search input to child components in Angular 2

Within my Angular 2 application, I am faced with the task of sending the value from an HTML search input to 3 child components only when the user pauses typing for 300ms and has entered a different value than what was previously in the input field. After r ...

How to adjust margins and padding for the <input type='radio' /> element using CSS?

Struggling to adjust the CSS for my radio buttons as their default settings are making my layout appear asymmetrical. I am using JavaScript to generate multiple forms and injecting a lot of inline styling like style='margin:0px padding:0px' to ma ...

Exploring the endless possibilities of querying MongoDB with ever-changing variables

I'm currently working on using node.js to retrieve json results from MongoDB. var http = require('http'); var mongo = require('mongoskin'); http.createServer(function (req, res) { var args = req.url.split("/"); console.log(ar ...

Analyzing the differences between a variable and a JSON object

In my project, I am attempting to match the selected user's gender and country with those stored in a JSON object. If the comparison yields a positive result, I want to display the corresponding "Value" for that gender and country from the JSON data. ...

Leveraging CSS in React/JSX

I am struggling to understand how to implement CSS with React. I have tried using inline styles but couldn't get it to work. Additionally, I am unsure where to apply CSS in my JSX code within the react class. For example, in one of my react classes, ...

Exploring and Presenting Arrays using React JS

Recently, I have started working with react js and I am trying to add a search functionality to filter an array in React. My goal is to allow the user to enter a character in the textbox and only see the names that contain that specific character. So far, ...

How to access v-for dynamically generated elements beyond the loop

How can I access a dynamically created item outside of a v-for loop in Vue.js? <li v-for="item in cart.items"> <h1>{{ item.product.name }}</h1> </li> <p>Is it possible to access {{ item.product.name }} out ...

Approach for retrieving users by utilizing forEach loop in Mongoose

I have a list of profile IDs that looks like get profiles [ '62d80ece61a85d738fa0c297', '62d80fb061a85d738fa0c29c' ] I am trying to iterate through this list and use each ID in the find() method Here is my code snippet: let total ...

Unable to initialize the bootstrap datepicker module

I'm having trouble initializing bootstrap-datepicker from this GitHub repository: https://github.com/uxsolutions/bootstrap-datepicker. I can't seem to get it to work properly or call any methods or events on it. My setup includes Laravel 5.4.7, ...

Troubleshooting: How can I ensure my custom scrollbar updates when jQuery niceselect expands?

I am currently utilizing the jquery plugins mCustomScrollbar and niceselect. However, I have encountered an issue when expanding the niceselect dropdown by clicking on it - the mCustomScrollbar does not update accordingly. I suspect this is due to the abso ...

Is the xmlhttprequest timeout/abort feature not functioning as anticipated?

Check out this snippet of my AJAX function: /** * This function initiates an AJAX request * * @param url The URL to call (located in the /ajax/ directory) * @param data The data to send (will be serialized with JSON) * @param callback The fu ...

React Native, state values are stagnant

I created an edit screen where I am attempting to update the post value through navigation v4 using getParams and setParams. However, when I modify the old value and click the save button, it does not update and no error is displayed. The old values still ...

What is the best way to deliver an HTTP request from the controller to my Ajax function?

Is there a way to send HTTP OK and error responses from the controller to my AJAX request? For example, using HttpStatusCode.OK and HttpStatusCode.BadRequest. When I inspect in my browser it shows impresion.js 304 not modified. $(document).ready(functi ...

Error: The property 'click' cannot be read from a null value during karma testing

I need help writing a karma/jasmine test case for the click event, but I am encountering an issue where the button is returning null. Any suggestions? Thanks in advance. it('should', async(() => { spyOn(component, 'clickMethod'); ...

Optimize Embedded Videos to Utilize Maximum HTML Element Width

I am facing an issue with embedding a Youtube video inside a td HTML element. I want the video to maintain its aspect ratio while expanding to fit the width of its parent td. My desired look for the video is like this: However, my current video appears l ...

I am trying to locate the XPath for the NG repeat element with the following code snippet: ng-repeat="thread in threads | orderBy:'-last_ts' | filter : globalSearch track by $index" Can you assist

<div ng-click="changeChatThread(thread, true)" class="item ui three column grid thread_item ng-scope active-thread" ng-class="{'active-thread' : selectedThread === thread.chat_id}" ng-repeat="thread in threads | orderBy:'-last_ts' | ...