0

I'm trying to use axios to get data from openweathermap, currently, I'm building the url by using a few methods to get the lat and lon from the user browser and then call a function that builds the url.

The url is built properly and without any issues, but when I try to call the api with axios, weird stuff happens (basically I'm getting my own page html code returned to me)

Here is the code:

let weather = new Vue ({
  el: '#weather',
  data: {
    error: '',
    apiUrl: '',
    city: '',
    country: '',
    icon: '',
    description: '',
    results: [],
  },
  methods: {
    getPosition: function() {
      if (navigator.geolocation){
        navigator.geolocation.getCurrentPosition(this.getUrl);
      }else{
        this.error = 'Geolocation is not supported.';
      }
    },
    getUrl: function(position){
      let lat = position.coords.latitude;
      let lon = position.coords.longitude;
      this.apiUrl = buildWeatherUrl(lat, lon);
    },
    getWeather: function(){
      axios.get(this.apiUrl).then(function (response) {
        this.city = response.data.name;
        this.results = response.data;
      }).catch( error => { console.log(error); });
    }
  },
  beforeMount() {
    this.getPosition();
  },
  mounted() {
    this.getWeather();
  }
});

This is my the first time using Vue and axios so I'm not sure what I'm doing wrong here. I also tried to add let self = this; and replace all this to self in the getWeather function but that didn't work.

The issue is that I'm trying to get the url from apiUrl which should get updated by the getUrl method. Although when getWeather is ran after mounted the url doesn't seem to be updated (if its hardcoded it works fine).

Thank you for the help.

FabioRosado
  • 427
  • 2
  • 10

3 Answers3

1

I suspect the problem is this line navigator.geolocation.getCurrentPosition(this.getUrl);.

When this.getUrl is called back by the navigator, the function no longer has the correct this, therefore this.apiUrl = buildWeatherUrl(lat, lon); will not work. Try binding this to this.getUrl, like so

getPosition: function() {
  if (navigator.geolocation){
    let getUrl = this.getUrl.bind(this)
    navigator.geolocation.getCurrentPosition(getUrl);
  }else{
    this.error = 'Geolocation is not supported.';
  }
},

Or simply navigator.geolocation.getCurrentPosition(this.getUrl.bind(this));

This function also has an incorrect this.

axios.get(this.apiUrl).then(function (response) {
    this.city = response.data.name;
    this.results = response.data;
  }).catch( error => { console.log(error); });

You'll either need to redo your previous fix:

I also tried to add let self = this; and replace all this to self in the getWeather function but that didn't work.

Or simply use an arrow function.

axios.get(this.apiUrl).then(response => {
    this.city = response.data.name;
    this.results = response.data;
  }).catch( error => { console.log(error); });

Here's a link to the definitive stack overflow answer about how to manage Javascript's this: https://stackoverflow.com/a/20279485/2498782

Scroll to the answer's section labeled "Common problem: Using object methods as callbacks/event handlers".

Eric Guan
  • 15,474
  • 8
  • 50
  • 61
  • Thank you so much for your help Eric, unfortunately, axios is still returning my own html code on `response.data`. I also didn't have any issues with the getPosition function before but I have added your suggestion to see if that would fix it, unfortunately it didn't – FabioRosado Jun 29 '18 at 08:00
0

I guess you registered the route as a POST request and not a GET request in the routes file. Just change it to GET and code will be fixed.

Toney Dias
  • 51
  • 5
  • This isn't the case as I am just working with a single js file where I am calling a vue instance – FabioRosado Jun 29 '18 at 10:34
  • can you console.log(this.apiUrl) and share the result? – Toney Dias Jun 29 '18 at 10:37
  • In your case, the url inside the axios.get(this.apiUrl) is not a legitimate url or is returning some kind of junk value as response. – Toney Dias Jun 29 '18 at 10:41
  • I'm using my api key there but basically, its something like: `"http://api.openweathermap.org/data/2.5/weather?units=metric&lat=51.2514596563852&lon=-0.1661086240457241&APPID={{apikey}}` – FabioRosado Jun 29 '18 at 10:43
  • I probably did something silly since I tried to comment out all the Vue. Created a data object, built the url and added it to the data object. When I console log the object the data shows empty but when I open it from the console the url is there. There must be some issue with my logic I guess – FabioRosado Jun 29 '18 at 10:45
  • do the practice of 'let self = this;' while using variables inside data. I have seen errors like this, changing the url inside the axios.get(url) usually solves the problem. – Toney Dias Jun 29 '18 at 10:51
  • Yeah I did that but it didn't help. I'm also trying to figureout why my object is empty but when I open it in the console it shows the url. Anyway thanks for the help – FabioRosado Jun 29 '18 at 10:55
0

I was able to fix this issue by commenting out all the vue code, then create an empty object called data and try to put the api url in that object. After failing constantly I realised that the url couldn't be passed to the object from within navigator.geolocation.getCurrentPosition so I played with global variables and something hit me, the issue was in how I was trying to get the url from within navigator.geolocation.getCurrentPosition

So I fixed the issue by adding lat and lon to data in the vue and then build the url before calling axios. That gave me the right results.

Here is the final code in case it's useful for someone.

    let weather = new Vue ({
  el: '#weather',
  data: {
    error: '',
    lat: 0,
    lon: 0,
    apiUrl: '',
    city: '',
    country: '',
    icon: '',
    description: '',
    results: [],
  },
  methods: {
    getPosition: function() {
      if (navigator.geolocation){
        var vm = this;
        navigator.geolocation.getCurrentPosition(this.updatePosition);
      }else{
        this.error = 'Geolocation is not supported.';
      }
    },
    updatePosition: function(position) {
        this.lat = position.coords.latitude;
        this.lon = position.coords.longitude;
    },
    getWeather: function(){
      let url = buildWeatherUrl(this.lat, this.lon);

      axios
      .get(url)
      .catch(function (error) {
        console.log(error);
      })
      .then(function (response) {
        console.log(response.data);
      });
FabioRosado
  • 427
  • 2
  • 10