简体   繁体   中英

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>

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM