2

Hey guys anyone who can help my out? Basically I want to make a breaking news footer that loops through the newsWire array and updates the text automatically. Problem is when I run my console.log(newsWire.length) outside the loadNewswire function it returns a 0, while the console.log inside returns 40 as it should?

Link: http://jsfiddle.net/u8y8zh72/3/

<html>
<head>
    <script src="https://code.jquery.com/jquery-2.1.4.js"></script>
    <style>
        footer {
            height: 75px;
            position: fixed;
            bottom: 0;
        }
    </style>
</head>
<body>
    <div class="container">
    <ul id="js-news" class="js-hidden"></ul>
    </div>
    <footer>
        <div class="container" id="newswiretxt">
        <span></span>
        </div>
    </footer>
</body>
<script type="text/javascript">
    var newsWire = [];
    function loadNewswire() {
        $.getJSON('http://api.nytimes.com/svc/news/v3/content/all/all.json',
        {'api-key': 'XXXXXXXXX'},
        function(data) {
            console.log(data)
            var newsWireTemp = [];
            for (var i = 0; i < data.results.length; i++) {
                var breakingNews = data.results[i];
                var breakingTitle = breakingNews.title;
                var breakingAbstract = breakingNews.abstract;
                newsWireTemp.push(breakingTitle);
                newsWireTemp.push(breakingAbstract);
            }
            newsWire = newsWireTemp;
            console.log(newsWire.length);
        });
    }
    loadNewswire();
    console.log(newsWire.length);


    $(document).ready(function() {
    var items = newsWire;
    $text = $('#newswiretxt span'),
    delay = 10; //seconds
    function loop (delay) {
        $.each(items, function (i, elm){
            $text.delay(delay*1E3).fadeOut();
            $text.queue(function(){
                $text.html(items[i]);
                $text.dequeue();
            });
            $text.fadeIn();
            $text.queue(function(){
                if (i == items.length -1) {
                    loop(delay);   
                }
            $text.dequeue();
            });
        });
    }
    loop(delay);
    });
</script>

  • `loadNewswire()` makes an asynchronous call. That means that `console.log(newsWire.length);` runs before the callback (`newsWire = newsWireTemp;`). You can tell that because you `console.log(newsWire.length)` is being output after `console.log(newsWire.length);` – Ruan Mendes Nov 09 '15 at 15:39

1 Answers1

0

The main thing is this:

...
loadNewswire();
console.log(newsWire.length);
...

When you call loadNewsWire, you're starting an asynchronous JSON request. However, the script execution won't wait for that function to complete, so it immediately runs the following console.log statement. At that point, the JSON request hasn't completed, so the newsWire array is still empty - which is why console.log(newsWire.length) returns 0 there.

Inside your loadNewsWire function, you have a callback function that gets executed when the JSON request has returned your data. At this point you're populating the array, and console.log(newsWire.length) gives you the expected count.


Update in response to comment:

Is there anyway to make the rest of my code wait for the function to execute?

Yes! $.getJSON is a convenience wrapper for $.ajax, which returns a jqXHR object (full juicy details in the jQuery documentation). You can add additional callbacks to that object, which is what you're actually doing inline in your call to $.getJSON. The following:

$.getJSON('http://...', { 'api-key': '...' },
    function (data) {
        // stuff
    });

Is equivalent to:

$.getJSON('http://...', { 'api-key': '...' })
    .done(function (data) {
        // stuff
    });

So, if you modify your loadNewswire to return the object returned from $.getJSON, you can attach a callback to it that will wait for the async operation to complete, and place the rest of your code inside that. If you change your code to this:

function loadNewswire() {
    return $.getJSON(
        ...
    );
};

You can then wrap the code you want to wait using one of the done, fail or always callbacks.

Your calling code would then look like this:

loadNewswire().done(function () {
    console.log(newsWire.length);
    // and any other code you want to hold until the async operation is complete
});

I'd suggest reading through the previously mentioned documentation - it's a bit heavy, but it gives a good overview of how to work with async requests using jQuery.

Martin Wedvich
  • 2,158
  • 2
  • 21
  • 37