0

I am running this block of asynchronous code on the first page that loads on my site (index page) and setting the resulting data in a global variable for use on other pages of the site. The problem is, on other pages of the site when I try to access the data returned and stored in the global variable, I can't do anything with the data until it is fully loaded, so I get errors that say the data is 'undefined'. What I need is a way to make sure the asynch code is completed and the data is available so that it can be used without error.

var apiInitData = new Object();

// This block is asynchronous and sets the data in apiInitData
bn.push(["init", function() {
    bn.apiId.init({
    loginSuccess: function (event){
        var params = {cross_app: true};
        bn.api.callApi("/access/list", params, function(data) {
        apiInitData.data = data.data;
        });
    }
    });
}]);

In other pages that load after the index page, I try to access this global variable:

console.log("apiInitData: ", apiInitData);

This does return the data in apiInitData. I can view the object in my console.

However, if I try to print the length of that data on the next line:

console.log("length", apiInitData.data.length);

I get an error:

Uncaught TypeError: Cannot read property 'length' of undefined

I know this is due to the apiInitData variable waiting for the asynch code to complete, but I don't know what I can do to wait for it. I have read about callback functions, but the more I read, the more confused I get and am just not seeing what needs to be done here.

How can I use the data in apiInitData on other pages of the site only after the data is completely fetched by the asynch code block?

DarkBee
  • 16,592
  • 6
  • 46
  • 58
Chris Nielsen
  • 839
  • 1
  • 16
  • 31
  • @Barmar: Can you please tell me how your suggested link answer's my question? Cause I am not seeing it. Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference – Chris Nielsen Sep 23 '19 at 19:15
  • Because the `loginSuccess:` function is called asynchronously, and `bn.api.callApi()` is also asynchronous. So the updates to `apiInitData` are not visible immediately. – Barmar Sep 23 '19 at 19:22
  • Yes, I understand that. Index page is where this block of asynch code runs and it sets this global variable. My question is: outside of index page, where I need the value stored in that global variable, how do I make those pages wait for the data to be loaded ? In other words, they need to wait for the asynch code on the index page to be completed. How do I make them wait for this data to be present? – Chris Nielsen Sep 23 '19 at 19:29
  • What do you mean by "outside of index page"? Every page has its own variables, global variables are only within a single page. If you need to pass data between pages, use `localStorage` or `sessionStorage`. – Barmar Sep 23 '19 at 19:31
  • I am using a CMS that uses PHP twigs for atomic design. When a page loads, all of the JavaScript from the various twigs gets loaded into memory. I can put console.logs at the top of each to see what order the twigs get loaded in. The JavaScript in index gets executed first, followed by the JavaScript in other twigs. We don't use sessionStorage, which is why I am trying to have this asynch code run only once and save the results to a global variable. – Chris Nielsen Sep 23 '19 at 19:36
  • So they're not really different pages, just different code that runs in the same page. Anything that depends on the result of the asynchronous code has to be run in the callbacks of the async functions. Or it should be in event handlers that run when the user does something later, that will be able to access the global variable after it has been updated. – Barmar Sep 23 '19 at 19:41
  • Yes! Now you have caught up to what I am asking. I believe I need to use a callback but I don't know where to place it or how to use it. Do I need to wrap my asynch code block in a function? I don't understand syntactically what to do. – Chris Nielsen Sep 23 '19 at 19:44
  • Just put what you want in the existing callback function, after `apiInitData.data = data.data;` – Barmar Sep 23 '19 at 19:49
  • I can't put everything there in the index page. Each twig that needs this data needs to do something different with it. Each page just needs the data that is being stored in apiInitData.data in order to change some html on that particular page. The problem is, those other pages need to wait for the data to be fetched before it can be used.. How do I get them to wait? – Chris Nielsen Sep 23 '19 at 19:52
  • I don't know Twig, maybe it has a framework for this. – Barmar Sep 23 '19 at 19:53
  • No, each twig has two components. One is the html template which is server side, and the other is the – Chris Nielsen Sep 23 '19 at 19:56
  • If Twig allows you to use asynchronous methods to load settings, it should have a way for you to register twigs that should be run after everything is loaded. This is no longer a basic JS question, it's a question specifically about Twig. – Barmar Sep 23 '19 at 19:59

1 Answers1

0

The issue here is that the line console.log("length", apiInitData.data.length); is executing before the line apiInitData.data = data.data;

So, I suggest you put the line console.log("length", apiInitData.data.length); inside a function "doWhateverWithApiInitData" and then you just call it after your API call has finished, something like this :

var apiInitData = new Object();

// This block is asynchronous and sets the data in apiInitData
bn.push(["init", function() {
    bn.apiId.init({
    loginSuccess: function (event){
        var params = {cross_app: true};
        bn.api.callApi("/access/list", params, function(data) {
        apiInitData.data = data.data;
        doWhateverWithApiInitData();  // Calling the function here should solve your issue
        });
    }
    });
}]);