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

3

5 Answers 5

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.

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

1 Comment

Got it. Thanks for explaining!
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.");
}

1 Comment

Thanks for the demo!
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.

2 Comments

@Pamblam it's not. Look closely at the curly braces.
That should have been obvious... and has the desired effect. Thank you!
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.

Comments

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

4 Comments

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)?
Then and wen are part of promises,that is like-it promise(ensures)the code will run after success/error execution of Ajax requests :)
Okay, I'll give it a try. Thanks again!
Unless I've misquoted you it doesn't seem to work for large amounts of data: 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.

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.