delay execution of a jQuery/javascript function until certain condition is met

I’m working on a web page that displays playing cards when a user clicks a button. When the button is clicked, the image on the page fades out, then a jquery ajax request is made to the server to fetch a random playing card, and then the new image fades back in. All of this worked without issue on my local server, but now that this project is being tested on another server the image fades out, then begins to fade in before the card image has been inserted in to the page ruining the effect. I am not very knowledgable of javascript, but I tried to fiddle with the fadeOut-fadeIn time to know avail. Could anyone help me to understand why this is occurring and guide me on how to fix it? How can I get the image to fade, then wait until the request has been made before fading the image in. Below is the function I’m using to execute this process.

$('.cardButton').on('click', function() {
var card = $(this).attr('cardSelector')
    req = $.ajax({
        url: '/wager', 
        type: 'GET',
        data: 'json',
        success: function(response){
            console.log(response);
        },
    });
    req.done(function(data) {
        $('#displayCard').fadeOut(1000, function() {
            $('#displayCard').attr('src', data.playingCard)
        });
        $('#displayCard').fadeIn(4000);
    });

});

Answer

You have correctly put the fading code in the done callback, so actually the request has already received a response before your code starts the fading.

But there is another asynchronous process at play here: the loading of the image will happen asynchronous too, so that when you set the src attribute, the execution will immediately continue with the fading in, not waiting for the image to have been loaded.

You can use the image’s load event to take this delay into account. Assign the handler once, with .one():

$('#displayCard').one("load", () => $('#displayCard').fadeIn(4000));
$('#displayCard').fadeOut(1000, function() {
    $('#displayCard').attr('src', data.playingCard);
});