1

I have a web application built with jQuery, and I need to load some JSON data before anything else is done. Currently, I'm doing it like this:

<html>
  ...
  <script type="text/javascript">
    // Load the data (directly injected into the HTML)
    var json = { ... };

    // Once the full DOM is loaded, do whatever I need
    $(whatever);

    function whatever() { ... }
  </script>
  ...
</html>

It works, but it's extremely ugly. I'd rather load the actual JSON file, for example using jQuery's getJSON with a callback function. But calling AJAX functions in a synchronous way isn't allowed anymore (at least with jQuery). So... how do I make sure that my whatever method isn't called until that callback has finished?

Just calling $(whatever) from my callback function is not an option, because I actually have many of those $() distributed across the different pages of the application.

7
  • 2
    Why would I actually have many of those $() distributed across the different pages of the application. stop you from using the callback? You could in each callback test if all the files you needed had loaded. Commented Oct 3, 2018 at 7:41
  • 1
    If the object is trustworthy, I think I would prefer your var json = { ... }; version, if possible - one less network request means slightly less time for the site's scripts to activate. If it's injected with PHP, for example, and you don't like var json = <?php echo ..., you can put the JSON into a script tag with a custom type instead and then parse its textContent. Also note that there's no such thing as a JSON object - JSON is a string notation. A string can be JSON, but an object never is, so you might call the variable something like data rather than json Commented Oct 3, 2018 at 7:41
  • 1
    "I have many of those [callbacks]" - just add a callback to this call $.getJSON(url).done(function(json) { whatever(json); }); - or are you saying you load the json all over the place? Or that all your doc.ready's rely on that json being preloaded? If so, instead of using a doc.ready, use listen for a custom event and raise the event on the $.getJSON handler. Or replicate the doc ready and call it when json loaded. Commented Oct 3, 2018 at 7:46
  • @CertainPerformance yes, it is injected - with Node.js. I already tried moving it to its own script tag, but then I ran into caching problems. As for the json variable, I just named that for the example, it's actually called data in my code :) Commented Oct 3, 2018 at 8:05
  • 1
    @freedomn-m you were right. I've managed to implement it using a custom event (I didn't know they even existed), combined with document.ready. Thanks! :) Commented Oct 3, 2018 at 9:47

2 Answers 2

1

There is a simpler way of doing things ;)

let json = {}
$(document).ready(() => {
  function whatever() {
    // do some stuff
    console.log('run the program');
  }
  $.getJSON('https://jsonplaceholder.typicode.com/users', (data) => {
      json = data;
      console.log(json);
    })
    .then(() => whatever());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Some paragraph</p>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help. Unfortunately, in my case that wouldn't work. It's a templated web application, I load the JSON file at the very beginning, at the header. Then, depending of the URL, it loads different HTML blocks, meaning different whatever functions. One page might have only one of those functions, another could have 2 or 3. It would be a nightmare to invert the execution order and call all of them from the getJSON callback.
1

I have found two different ways to implement it. First, using the .holdReady() function in jQuery:

The $.holdReady() method allows the caller to delay jQuery's ready event. This advanced feature would typically be used [...] to load [...] before allowing the ready event to occur

So in my case, the code should look like this:

<html>
  ...
  <script type="text/javascript">
    var json = {};
    $.holdReady(true);
    $.getJSON(url, '', function(data) {
      json = data;
      $.holdReady(false);
    });

    $(whatever);
  </script>
  ...
</html>

Another option, using custom events (thanks to freedomn-m's suggestion in the comments), would be something like this:

<html>
  ...
  <script type="text/javascript">
    var json = {};
    // Request the JSON file
    $.getJSON(url, '', function(data) {
      // When it's retrieved, store the data in the `json` variable
      json = data;
      // And when the DOM is ready...
      $(function() {
        // ...trigger the custom `jsonReady` event
        $(document).trigger('jsonReady');
      });
    });
  </script>
  ...
</html>

The only change required is to replace all the $(whatever); for $(document).on('jsonReady', whatever);.

3 Comments

Why not declare whatever as a function and call it in the $.getJSON callback?
Because "Just calling $(whatever) from my callback function is not an option, because I actually have many of those $() distributed across the different pages of the application."
callback are the way to go. you may need to design/organize your app logic better,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.