Joao Nunes
Joao Nunes

Reputation: 33

Can't extract data with getJSON

Im doing the freecampcode curriculum right now i'm at the local weatherapp.

My problem here is everytime i try to use, i get apiLink is not defined. I understand that the .getJSON part can't connect with the var defined inside the definedCordinates function.

Also i tried to use the direct api link on the .getJSON function, but even with that i get 0 input from json, im using console.log(data) and $("#temp").text to check the input from json.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>My Local Weather App</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="custom.css">.
    <script type="text/javascript">
    $(document).ready(function(){
        getCordinates();
        $.getJSON(apiLink, function(data){
            console.log(data);
        })
    })

    function getCordinates(){
        navigator.geolocation.getCurrentPosition(definedCordinates);
    }

    function definedCordinates(position){
        var latitude = Math.floor(position.coords.latitude);
        var longitude = Math.floor(position.coords.longitude);
        var apiLink = "api.openweathermap.org/data/2.5/weather?lat=" + latitude +"&lon="+ longitude +"&APPID=##########";
        return apilink;
}
    </script>


<body>
    <div class="container-fluid">
        <div class="row" id="titleRow">
            <div class="col-md-4 col-md-offset-4">
                <h1>My Local Weather App</h1>
            </div>
        </div>
        <div class="row" id="locationRow">
            <div class="col-md-4 col-md-offset-4">
                <div class=row">
                    <div class="col-md-6" style="background-color: grey">
                        <p style="text-align:center">icon</p>
                    </div>
                    <div class="col-md-6" style="background-color: yellow">
                        <p style="text-align:center" id="temp">temp</p>
                    </div>
                </div>
            </div>
        </div>
        <div class="row" id="dataRow">
            <div class="col-md-6 col-md-offset-3">
                <div class="row">
                    <div class="col-md-4" style="background-color: grey">
                        <p id="name"> city name</p>
                    </div>
                    <div class="col-md-4" style="background-color: yellow">
                        <p> sky</p>
                    </div>
                    <div class="col-md-4" style="background-color: grey">
                        <p> wind</p>
                    </div>
                </div>
            </div>
        </div>
        <div class="row" id="poweredBy">
            <div class="col-md-6 col-md-offset-3">
                <div class="row">
                    <div class="col-md-6" id="powered">
                        <p> Powered by openweathermap.org API </p>
                    </div>
                    <div class="col-md-6"style="background-color: yellow">
                        <p> button celsius or farh </p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Upvotes: 1

Views: 234

Answers (3)

trincot
trincot

Reputation: 350781

The function getCordinates does not return anything, and even if it did, it cannot return the URL synchronously, because the callback definedCordinates will only be called later, asynchronously. Secondly, the return value from that callback (which is the URL) is currently not used, but disappears in oblivion.

There are several ways to solve this, but in this case adding a promise (to the promise that $.getJSON already is) seems like a nice solution:

$(document).ready(function(){
    getCordinates().then(function(apiLink) {
        // this executes when the promise returned by getCordinates is resolved:
        return $.getJSON(apiLink);
    }).then(function (data) {
        // this executes when the promise returned by getJSON is resolved:
        console.log(data);
    });
})

function getCordinates() {
    // return a promise that resolves when you get the current position:
    return new Promise(function (resolve) {
        navigator.geolocation.getCurrentPosition(function (position) {
            resolve(definedCordinates(position));
        });
    });
}

The function definedCordinates can stay like it is, but correct the wrong spelling of apiLink in the return statement.

Upvotes: 1

hairmot
hairmot

Reputation: 2975

getCordinates needs to return a value (your url) and you need to pass that value to getJSON rather than an object (which doesn't exist in the same scope as your document ready!)

a more likely fix would be something like:

$(document).ready(function(){
    var url = getCordinates();
    $.getJSON(url, function(data){
        console.log(data);
    })
})

function getCordinates(){
    navigator.geolocation.getCurrentPosition(definedCordinates);
}

function definedCordinates(position){
    var latitude = Math.floor(position.coords.latitude);
    var longitude = Math.floor(position.coords.longitude);
    var apiLink = "api.openweathermap.org/data/2.5/weather?lat=" + latitude +"&lon="+ longitude +"&APPID=##########";
    return apilink;
}

You will also run into an issue as you are not passing anything into definedCoordinates.

This could be solved by making apiLink a global variable but this is not a good way to solve the problem

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337637

The issue is because your apiLink variable is defined in the definedCordinates() function, which is well out of scope of the document.ready handler.

To fix this you need to restructure your logic so that the apiLink is available to the AJAX request by using the appropriate callbacks on async methods. Try this:

$(document).ready(function(){
    getCordinates(function(apiLink) {
        $.getJSON(apiLink, function(data) {
            console.log(data);
        })
    });
})

function getCordinates(callback) {
    navigator.geolocation.getCurrentPosition(function(position) {
        var latitude = Math.floor(position.coords.latitude);
        var longitude = Math.floor(position.coords.longitude);
        var apiLink = "https://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&APPID=##########"
        callback && callback(apiLink)
    });
}

Also note that the apiLink should be an absolute URL, ie. it needs a http:// or https:// prefix.

Upvotes: 1

Related Questions