2

I'm having trouble with my functions running before Ajax requests (the first to a local JSON, the second to an online resource) have finished.

In this example I want countTheMovies to run at the end after my application has got all the information it needs and populated the divs. Instead it's running straight away.

I tried to delay it using an if condition, but with no joy. I've also tried with callbacks, but think I must be getting those wrong (I'm assuming callbacks are the answer). I'm aware of timed delays, but because in the actual project I'm sourcing 250+ movies (and because a timed delay seems like cheating) I thought I'd ask here instead.

Can anyone recommend JavaScript or jQuery code to fix this problem?

$(function(){
  getMovieList();
});

function getMovieList() {
  $.ajax({
    url: "movielist.json",
    type: "GET",
    dataType: "JSON",
    success: function(data) {
      for (var i = 0; i < data.length; i++) {
        var title = data[i].title.toLowerCase().split(" ").join("+");
        var year = data[i].year;
        i === data.length - 1
          ? getMovieInfo(title, year, true)
          : getMovieInfo(title, year, false);
      }
    }
  });
}

function getMovieInfo(title, year, isLast) {
  $.ajax({
    url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
    type: "GET",
    crossDomain: true,
    dataType: "JSON",
    success: function(val) {
      if (!val.Error) {
        movie = title.replace(/[^a-z0-9\s]/gi, '');
        $("#app").append(
          // appending info to divs
        );
      }
    }
  });
  if (isLast) countTheMovies();
};

function countTheMovies() {
  $("#app").append("There are " + $(".movie").length + " movies.");
}

A plunker of my failings: https://plnkr.co/edit/0mhAUtEsaOUWhkZMJqma?p=preview

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dedaumiersmith
  • 337
  • 4
  • 14

5 Answers5

2

You've almost got it!

The same way that you call getMovieInfo in the success callback of getMovieList, you should be calling countTheMovies in the success callback of getMovieInfo.

Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128
2

As Jacob said above, move the countTheMovies call inside the AJAX request.

$(function(){
  getMovieList();
});

function getMovieList() {
  $.ajax({
    url: "movielist.json",
    type: "GET",
    dataType: "JSON",
    success: function(data) {
      for (var i = 0; i < data.length; i++) {
        var title = data[i].title.toLowerCase().split(" ").join("+");
        var year = data[i].year;
        i === data.length - 1 
          ? getMovieInfo(title, year, true) 
          : getMovieInfo(title, year, false);
      }
    }
  });
}

function getMovieInfo(title, year, isLast) {
  $.ajax({
    url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
    type: "GET",
    crossDomain: true,
    dataType: "JSON",
    success: function(val) {
      if (!val.Error) {
        movie = title.replace(/[^a-z0-9\s]/gi, '');
        $("#app").append(
          // appending info to divs
        );
        if (isLast) countTheMovies();
      }
    }
  });
};

function countTheMovies() {
  $("#app").append("There are " + $(".movie").length + " movies.");
}
Cameron
  • 694
  • 4
  • 16
1

Just put your countTheMovies() logic inside of the success callback of the AJAX request in getMovieInfo if you want it to run on success.

Jacob
  • 77,566
  • 24
  • 149
  • 228
1

You can call your countTheMovies() function from inside the success field of your Ajax call. This way it will make the function call when you intend it to.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Justin
  • 154
  • 1
  • 17
0

Try out this

$(function(){
      getMovieList();
    });

    function getMovieList() {
    $.when( $.ajax({
        url: "movielist.json",
        type: "GET",
        dataType: "JSON",
        success: function(data) {
          for (var i = 0; i < data.length; i++) {
            var title = data[i].title.toLowerCase().split(" ").join("+");
            var year = data[i].year;
            i === data.length - 1 
              ? getMovieInfo(title, year, true) 
              : getMovieInfo(title, year, false);
          }
        }
      }) ).then(function( data, textStatus, jqXHR ) {
      countTheMovies();
    });
    }

      function getMovieInfo(title, year, isLast) {
      $.ajax({
        url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
        type: "GET",
        crossDomain: true,
        dataType: "JSON",
        success: function(val) {
          if (!val.Error) {
            movie = title.replace(/[^a-z0-9\s]/gi, '');
            $("#app").append(
              // appending info to divs
            );
          }
        }
      });
    };
    function countTheMovies() {
      $("#app").append("There are " + $(".movie").length + " movies.");
    }
misss-popcorn
  • 591
  • 2
  • 12
  • Hi @urvashi, thanks for the advice and introducing me to some new code! I can't test it at the moment but why do you recommend using "when" and "then" rather than simply moving my call (as per the answers below)? – dedaumiersmith Aug 08 '16 at 17:16
  • Then and wen are part of promises,that is like-it promise(ensures)the code will run after success/error execution of Ajax requests :) – misss-popcorn Aug 08 '16 at 17:19
  • Okay, I'll give it a try. Thanks again! – dedaumiersmith Aug 08 '16 at 17:23
  • Unless I've misquoted you it doesn't seem to work for large amounts of data: http://plnkr.co/edit/0mhAUtEsaOUWhkZMJqma?p=preview (if you search for the console.log message, "there are x movies", it pops up about halfway through the cycle. – dedaumiersmith Aug 08 '16 at 18:16