dedaumiersmith
dedaumiersmith

Reputation: 347

JavaScript/jQuery callback using Ajax

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

Upvotes: 2

Views: 94

Answers (5)

Justin
Justin

Reputation: 154

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.

Upvotes: 1

misss-popcorn
misss-popcorn

Reputation: 600

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.");
    }

Upvotes: 0

Cameron
Cameron

Reputation: 694

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.");
}

Upvotes: 2

Matthew Herbst
Matthew Herbst

Reputation: 31963

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.

Upvotes: 2

Jacob
Jacob

Reputation: 78850

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

Upvotes: 1

Related Questions