Gsquare
Gsquare

Reputation: 3

Load JSON file at runtime

I have HTML file with script

<script src="tralBA.json" type="text/javascript"></script>

where tralBA.json:

var datiTral = {  
    "tral": 
    [
        {"trl_id": "BA_01", "longitude": 16.58, "latitude": 41.09},
        {"trl_id": "BA_02", "longitude": 16.578, "latitude": 41.112}, 
        {"trl_id": "BA_03", "longitude": 16.544, "latitude": 41.09}, 
        {"trl_id": "BA_04", "longitude": 16.556, "latitude": 41.08},        
        {"trl_id": "BA_05", "longitude": 16.580, "latitude": 41.085},       
        {"trl_id": "BA_06", "longitude": 16.590, "latitude": 41.096}
]}

and a JS file:

.......
var clusterTral = {};
clusterTral.tral = null;
clusterTral.tral = datiTral.tral; 

and i have clusterTral.tral correctly fed up.

Later i need to define and use my tralBA.json file at RunTime. I try to do it by the following function

function showClusterTral(pv) {

var filename = "tral" + pv + ".json";
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', filename);
document.head.appendChild(script);  
clusterTral.tral = datiTral.tral;
.....

}

but i get the error "Uncaught ReferenceError: datiTral is not defined" How can i solve? Thank you.

Upvotes: 0

Views: 1173

Answers (1)

Vanquished Wombat
Vanquished Wombat

Reputation: 9535

The reason for the issue is that the script tag is still loading when the code that references the value is executed. This can by proven by referring to the value of the loaded variable immediately after the script file is called for, and again one second later (you may need to vary the timeout value in your configuration). The immediate test logs '[undefined]' and the delayed log shows the value of the tral object.

function showClusterTral(pv) {

var filename = "tral" + pv + ".json";
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', filename);
document.head.appendChild(script);  
var clusterTral = {};
try {
    clusterTral.tral = datiTral.tral;
    console.log('Immeditate tral=' + JSON.stringify(clusterTral.tral))
    }
catch (err) {
    console.log('Immeditate tral=[not defined]')
    }
setTimeout(function(){
    clusterTral.tral = datiTral.tral;
    console.log('Delayed tral=' + JSON.stringify(clusterTral.tral))
    }, 1000)
}

showClusterTral("BA")  // kick off the function

In otherwords the script fetch we request is async - the JS carries on from the next line without waiting for the script to arrive. The answer will then be some type of ajax request.

Note: the loading of script in this way is known as script injection and it is much discussed under the banner 'JSONP' where it is used to overcome same-origin policies. Whilst cross-domain script injection in this stylee 'can' be done you should think about the risks of some black-hat modifying the innocent source script you are expecting. Basically do not inject script you are not in control of.

And so to the solution - a quick read of Dave Walsh Blog on the subject leads to the answer below. Note that this required JQuery - you do not specify that this must be a pure JS solution so hopefully this is viable for you:

function showClusterTral(pv) {

var clusterTral = {};

jQuery.getScript("tral" + pv + ".json")
    .done(function() {
        /* yay, all good, do something */
        clusterTral.tral = datiTral.tral;
        console.log('Delayed tral=' + JSON.stringify(clusterTral.tral))     
    })
    .fail(function() {
        /* boo, fall back to something else */
        console.log("Some error in the path maybe ?")   
});

}

showClusterTral("BA") // kick off the function

The difference here is that the use of the delivered variable now depends on the done fork of the getScript() function firing, meaning we don't refer to the variable from the loaded script until the file is loaded in the browser JS context. There is also a fail handler that we can use to gracefully handle any unexpected issues that mean the script does not load.

I cannot add this as a snippet as it refers to an external file but if you chuck the above in a web page and save the tralBA.json file as defined by the OP then it all works.

Upvotes: 2

Related Questions