Thomas Smyth
Thomas Smyth

Reputation: 522

Javascript Sleep for x seconds

On my website I have a javascript function that does an AJAX call to get account's information then opens a modal where you can see and edit the information. An AJAX call is used to change the detail in the database you select and then refreshes the original function to re-open the modal to refresh the information there. It seems however, that occasionally (1/2+ times done) the details don't update fast enough in the DB before the functions that collects the details to display is run again.

I want to try delaying when the second function is ran to give a better chance for the details being updated before being fetched again, however I am unsure on how to do this. I've tried various things, however the one that seems the most popular, as shown below, does not work. Do you have any suggestions how I can fix it so the code pauses for x time before continuing?

 function ChangeRank(StrUsername, StrPage)
 {
     var StrRank = $("#sltRank option:selected").val();
     //Updates info in database
     ModeratorEditAccount(StrUsername, StrRank, 'Rank', StrPage);
     //Displays info again
     setTimeout(ModeratorActions(StrUsername, StrPage), 30000);
 }

 function ModeratorEditAccount(StrUsername, Value, StrDetail, StrPage)
 {
     $.post('http://thomas-smyth.co.uk/functions/php/fncmoderatoreditaccount.php',
     {
         StrUsername: StrUsername,
         Value: Value,
         StrDetail: StrDetail
     }, function(data)
     {
         if (data == 0)
         {
             $("#mdlGeneral > div").modal("hide");
             if (StrSearchType == "Basic")
             {
                 UserBasicSearch(StrPage);
             }
             else
             {
                 UserAdvanceSearch(StrPage);
             }
         }
         else if (data == 10)
         {
             window.location.href = "http://thomas-smyth.co.uk/login.php";
         }
     });
 }

 function ModeratorActions(StrUsername, StrPage)
 {
     $.post('http://thomas-smyth.co.uk/functions/php/fncgetaccountdetails.php',
     {
         StrUsername: StrUsername
     }, function(data)
     {
         var returnValue = JSON.parse(data);
         if (data == 5)
         {}
         else
         {
             if (returnValue["StrGender"] == "M")
             {
                 StrGender = "Male";
             }
             else
             {
                 StrGender = "Female";
             }
             $("#mdlEditProfile").html('<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content" style="border-radius: 25px;"><div class="box box-widget widget-user-2"><div class="widget-user-header bg-yellow"><div class="widget-user-image"><img class="img-circle" src="../dist/img/user2-160x160.jpg" alt="User Avatar"></div><h3 class="widget-user-username">' + returnValue['StrSurname'] + ', ' + returnValue['StrForename'] + ' (' + returnValue['StrUsername'] + ')</h3><h5 class="widget-user-desc">Member Since: ' + returnValue['DteRegDate'] + '</h5></div>\<div class="box-footer no-padding"><ul class="nav nav-stacked"><li><a><strong>Name: </strong>' + returnValue['StrSurname'] + ', ' + returnValue['StrForename'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeNameOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['StrSurname'] + '\', \'' + returnValue['StrForename'] + '\', \'' + StrPage + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Username: </strong>' + returnValue['StrUsername'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeUsernameOpen(\'' + returnValue['StrUsername'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Date of Birth: </strong>' + returnValue['DteDoB'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeDoBOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['DteDoB'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Gender: </strong>' + returnValue['StrGender'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeGenderOpen(\'' + returnValue['StrUsername'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Account Rank: </strong>' + returnValue['StrRank'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeRankOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['StrRank'] + '\', \'' + StrPage + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li></ul></div></div></div></div></div>');
             $("#mdlEditProfile > div").modal("show");
         }
     });
 }   

Upvotes: 0

Views: 588

Answers (4)

Jerry Chin
Jerry Chin

Reputation: 667

setTimeout(ModeratorActions(StrUsername, StrPage), 30000);

It's not the correct way to pass arguments to the callback, in your case ModeratorActions will be invoked immediately, so that probably explains why it works unreliably, you should use the following syntax:

setTimeout(ModeratorActions, 30000, StrUsername, StrPage)

Note: the above syntax passing additional arguments to callback function doesn't work for IE 9 and below, read setTimeout on Mozilla for workaround.

EDIT: I should type more fast next time.

Upvotes: 0

trincot
trincot

Reputation: 350270

You could use the promise that $.ajax returns, which will have the then property. You can then pass a function to the then property which will only be called when the Ajax call has finished. So then you don't need a timeout anymore:

function ModeratorEditAccount(StrUsername, Value, StrDetail, StrPage)
{
    // Return the promise to the caller 
    return $.post('http://thomas-smyth.co.uk/functions/php/fncmoderatoreditaccount.php',
       /// etc ...
}

Then in your ChangeRank function you can make use of the above change:

function ChangeRank(StrUsername, StrPage)
{
    var StrRank = $("#sltRank option:selected").val();
    //Updates info in database
    ModeratorEditAccount(StrUsername, StrRank, 'Rank', StrPage).then(function () { 
        // This only executes when previous ajax has returned
        //Displays info again
        ModeratorActions(StrUsername, StrPage);
    }, function () {
        // an error occurred, like a timeout.
        ModeratorActions(StrUsername, StrPage);
    });
}

Note that your timeout call was wrong anyway, since you did not pass a function reference to it, but executed ModeratorActions immediately. You could have used bind to pass the reference and still have the arguments passed to it when the actual call was made 30 seconds later:

setTimeout(ModeratorActions.bind(null, StrUsername, StrPage), 30000);

But this solution is still less practical compared to the promise-based solution, as the promise really fulfils when the Ajax transaction completes, and not a second later.

Upvotes: 2

Tom
Tom

Reputation: 4292

Why not move the function to reload the data into the success method of the function used to save it? Rather than hoping the save request will complete in 3 seconds?

function ChangeRank(StrUsername, StrPage)
 {
     var StrRank = $("#sltRank option:selected").val();
     //Updates info in database
     ModeratorEditAccount(StrUsername, StrRank, 'Rank', StrPage);
     //Displays info again
     // Removed
     //setTimeout(ModeratorActions(StrUsername, StrPage), 30000);
 }

 function ModeratorEditAccount(StrUsername, Value, StrDetail, StrPage)
 {
     $.post('http://thomas-smyth.co.uk/functions/php/fncmoderatoreditaccount.php',
     {
         StrUsername: StrUsername,
         Value: Value,
         StrDetail: StrDetail
     }, function(data)
     {
         if (data == 0)
         {
             $("#mdlGeneral > div").modal("hide");
             if (StrSearchType == "Basic")
             {
                 UserBasicSearch(StrPage);
             }
             else
             {
                 UserAdvanceSearch(StrPage);
             }
             // Added here, though you may want to move it
             ModeratorActions(StrUsername, StrPage)

         }
         else if (data == 10)
         {
             window.location.href = "http://thomas-smyth.co.uk/login.php";
         }
     });
 }

 function ModeratorActions(StrUsername, StrPage)
 {
     $.post('http://thomas-smyth.co.uk/functions/php/fncgetaccountdetails.php',
     {
         StrUsername: StrUsername
     }, function(data)
     {
         var returnValue = JSON.parse(data);
         if (data == 5)
         {}
         else
         {
             if (returnValue["StrGender"] == "M")
             {
                 StrGender = "Male";
             }
             else
             {
                 StrGender = "Female";
             }
             $("#mdlEditProfile").html('<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content" style="border-radius: 25px;"><div class="box box-widget widget-user-2"><div class="widget-user-header bg-yellow"><div class="widget-user-image"><img class="img-circle" src="../dist/img/user2-160x160.jpg" alt="User Avatar"></div><h3 class="widget-user-username">' + returnValue['StrSurname'] + ', ' + returnValue['StrForename'] + ' (' + returnValue['StrUsername'] + ')</h3><h5 class="widget-user-desc">Member Since: ' + returnValue['DteRegDate'] + '</h5></div>\<div class="box-footer no-padding"><ul class="nav nav-stacked"><li><a><strong>Name: </strong>' + returnValue['StrSurname'] + ', ' + returnValue['StrForename'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeNameOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['StrSurname'] + '\', \'' + returnValue['StrForename'] + '\', \'' + StrPage + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Username: </strong>' + returnValue['StrUsername'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeUsernameOpen(\'' + returnValue['StrUsername'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Date of Birth: </strong>' + returnValue['DteDoB'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeDoBOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['DteDoB'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Gender: </strong>' + returnValue['StrGender'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeGenderOpen(\'' + returnValue['StrUsername'] + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li><li><a><strong>Account Rank: </strong>' + returnValue['StrRank'] + '<span class="pull-right badge bg-blue" style="cursor: pointer;" onclick="ChangeRankOpen(\'' + returnValue['StrUsername'] + '\', \'' + returnValue['StrRank'] + '\', \'' + StrPage + '\')"><i class="fa fa-fw fa-edit"></i> Edit</span></a></li></ul></div></div></div></div></div>');
             $("#mdlEditProfile > div").modal("show");
         }
     });
 }   

Upvotes: 1

Patrick Moore
Patrick Moore

Reputation: 13344

setTimeout() may behave as expected when function is wrapped in function(){ ... }

setTimeout( function(){ ModeratorActions(StrUsername, StrPage) }, 30000);

See here: JavaScript.setTimeout

Upvotes: 3

Related Questions