Reputation: 8142
I'm trying to implement the following scenario on my web page:
next
buttonI checked for solutions of similar synchronization problems:
but couldn't really adapt them to my case.
The following snippet gets executed every time the user presses the next
button.
// get timing for instruction reading
var currentTime = new Date().getTime();
totalTime = currentTime - startTime;
console.debug("Time: " + totalTime);
if (flag_instructions_pressed == false){
$.ajax({
url: "/IsNewUser/",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
"_user_id": _user_id,
}),
dataType: "text",
success: function( returned_data ) {
_user_exp = parseInt(returned_data);
flag_instructions_pressed = true;
}
});
}
if ( totalTime < 60000 && _user_exp == 0) {
alert("You have to wait 60 seconds");
return;
}
ajax
request will return a string with the number of previous visits of the user in question, and it should be executed only once for this session (cause it adds the user to the database). The result is stored in the global variable _user_exp
.I have the following problem:
Even if a user has visited the page multiple times he will still be shown the alert since the
if
statement is executed before thesuccess
function from theajax
request.
How do I solve it?
NOTE 1: I cannot simply move the if
statement into the success
function because that should still be executed even after the flag_instructions_pressed
is set to true
. flag_instructions_pressed
is just a flag initialized to false
that gets set to true
after the ajax
request is performed. This prevents the request from happening again when the code is executed a second time.
NOTE 2: Obviously if I put an alert (or simply a timeout) before the if
statement, everything works fine. But I think it is bad programming practice and would like to learn how to deal with this type of synchronization problems.
Upvotes: 3
Views: 1723
Reputation: 11
How about turning the if statement into a function:
function testTime() {
if ( totalTime < 60000 && _user_exp == 0) {
alert("You have to wait 60 seconds");
return;
}
}
And then make the other if statement into an if/else, calling this function both in the else block (flag_instructions_pressed == true
) and in the success function of the ajax call (flag_instructions_pressed == false
):
if (flag_instructions_pressed == false){
$.ajax({
url: "/IsNewUser/",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
"_user_id": _user_id,
}),
dataType: "text",
success: function( returned_data ) {
_user_exp = parseInt(returned_data);
flag_instructions_pressed = true;
testTime();
}
});
} else {
testTime();
}
Upvotes: 1
Reputation: 101738
One solution to this is to make use of promises. They serve as a placeholder for a future value and you can "check their future value" multiple times:
var newUserCheck;
function nextButtonHandler() {
// get timing for instruction reading
var currentTime = new Date().getTime();
totalTime = currentTime - startTime;
console.debug("Time: " + totalTime);
if (!newUserCheck) {
newUserCheck = $.ajax({
url: "/IsNewUser/",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
"_user_id": _user_id,
}),
dataType: "text"
}).then(function ( returned_data ) {
_user_exp = parseInt(returned_data);
return _user_exp;
});
}
newUserCheck.then(function (user_exp) {
if ( totalTime < 60000 && user_exp === 0 ) {
alert("You have to wait 60 seconds");
return;
}
// otherwise, complete the "next button procedure" here
});
}
Upvotes: 1