0

For my final project, I am accessing an API, and I want to display data from that API in a web-page (the API provides data on forecast electricity generation from solar PV in the UK, it's provided by Sheffield University, hence the names).

I've written a python function that accesses the API, and I pass this to javascript using a $.getJSON(Flask.url_for... call. I've tested the python script and it's working - i.e. getting the right data. And I've used some console logging in javascript to check that the $.getJSON... call is working - and it is. However, I'm unable to pass the data to HTML.

Here's my javascript code:

/**
* Call sheffield function from sheffield_pv.py to add content to 'sheffield_div'
*/

$(document).ready(function sheffield(){

    var contents = ''; // instantiate an empty string to hold the contents to be sent back to html
    contents += '<p>Forecast generation for next hour [';
    var success = "SHEFFIELD SUCCESS"; // text string to log to console on successful operation

    $.getJSON(Flask.url_for("sheffield")).done(function(sheffield, textStatus, jqXHR) {

        contents += sheffield.generation_MW;

        console.log(sheffield.generation_MW);
        console.log(success);
    })
    .fail(function(jqXHR, textStatus, errorThrown) {
        //log error to browser's console
        console.log(errorThrown.toString());
    });

    contents += '] MW</p>';
    contents += '<p>THIS TEXT ADDED FROM JAVASCRIPT IN SHEFFIELD.JS</p>'; // Temp to check if this script is working
    document.getElementById('sheffield_test_div').innerHTML += contents; //'sheffield_div' is the div id for the div in html

});

You can see the output from the attached screenshot:

enter image description here

On the left you can see the square brackets - which should have the data from sheffield.generation_MW inserted.

On the right you can see Chrome's inspector window - showing no errors and in fact logging that the $.getJSON(... call has been completed with both my "success" message and the current figure for sheffield.generation_MW (352).

So, what's going on? I've done (a lot!) of reading around on this and I think the problem is due to asynchronicity in javascript. As I understand it, the $.getJSON(... call runs asynchronously, and while it's waiting for that to complete, javascript completes the rest of the code. That means that my variable contents is updated, and this gets passed to the sheffield_test.div and displayed. This div is never updated when the $.getJSON(... call completes. So the return from this call just gets logged in javascript's console, and nothing is done with it.

My question is - how do I fix this?

Thanks, Matt

0

So, I've done some more reading and learned how to make callback functions work. I'm leaving the question up because it might help someone else. Thanks so much to this tutorial:

https://github.com/maxogden/art-of-node#callbacks

My code is now as follows:

/**
 * Gets data from Sheffield Solar API.
 * See: https://www.solar.sheffield.ac.uk/pvlive/api/
 * Huge thanks to this tutorial for helping me with callback functions! https://github.com/maxogden/art-of-node#callbacks
 */

//call sheffield function from sheffield_pv.py to add content to 'sheffield_div'

$(document).ready(function sheffield(){

    var contents = '<p>This forecast is for the 30 minutes before and after '; // string to hold the contents to be sent to html
    var first ='DO THIS FIRST'; // to be logged to console as a check my call back functions are working
    var second = 'DO THIS SECOND'; // "
    var third = 'DO THIS LAST'; // "
    var sheffieldURL = 'https://www.solar.sheffield.ac.uk/pvlive/api/';

    // get the date and time of the forecast. Use a callback function to make sure this finishes before moving on.
    function getDateTime (callback) {
        $.getJSON(Flask.url_for("sheffield")).done(function(sheffield, textStatus, jqXHR) {
            contents += sheffield.datetime_GMT;
            console.log(first);
            console.log(sheffield.datetime_GMT);
            callback();
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            //log error to browser's console
           console.log(errorThrown.toString());
        });
    }

    // function to be called-back in getDateTime()
    function addToContents(){
        contents += ' </p>';
    }

    // get forecast PV generation. Use a callback function to make sure this finishes before moving on.
    function getGeneration (callback) {
        $.getJSON(Flask.url_for("sheffield")).done(function(sheffield, textStatus, jqXHR) {
            contents += '<p>Forecast PV generation in the UK for this hour: ';
            contents += sheffield.generation_MW;
            console.log(second);
            console.log(sheffield.generation_MW);
            callback();
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            //log error to browser's console
            console.log(errorThrown.toString());
        });
    }

    // function to be called-back in getGeneration()
    function finishContents(){
        contents += ' MW</p>';
        contents += '<p>Data supplied by The University of Sheffield via its PV_Live API:</p>';
        contents += '<p>';
        contents += '<a href = https://www.solar.sheffield.ac.uk/pvlive/api/>' + 'www.solar.sheffield.ac.uk/pvlive/api/' + '<a>';
        contents += '</p>';
        document.getElementById('sheffield_test_div').innerHTML += contents; //'sheffield_div' is the div id for the div in html
        console.log(third);
    }

    //call getDateTime with addToContents() as the function that gets called back
    getDateTime (addToContents);

     // call getGeneration() with finishContents() as the function that gets called back
    getGeneration (finishContents);
});

My output is:

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .