Reputation: 522
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
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
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
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
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