Reputation: 266
This function is called after an ajax get request gets results back
function handleLogin() {
if ($("#imalogin").length) {
alert("Your login has expired, please log back in");
window.location.replace("login.aspx");
}
}
This is a function that calls it
function addEstablishments() {
$.get(encodeURI("addEstablishment.aspx?locationCode=" + $('#locationCode').val()), function (data) {
$("#dbCheck").html(data);
handleLogin();
}).done(function (){
if ($("#duplicateEstablishment").length) {
$("#locationCodeError").html("Location code already used")
}
else {
alert("Location added");
getEstablishments();
hideLocationForm();
}
}).fail(function () {
alert("Failed to add location. Please try again in a few seconds");
$("#locationAddressError").html("Could not confirm address");
});
}
I would "expect" handleLogin
to show the alert inside of it, which it does, and then redirect immediately and the rest of the code would not execute. But this is the strange land of javascript, so the alert in the .done
event of addEstablishments
fires as well before it redirects, so people get a message that it has been added when it has not, and they get redirected to a login page, log in and find out it was never added. So there is some obscure javascript rule that I'm not aware of or is this because I can't call handleLogin
where I am, and need to call it in .done?
Upvotes: 3
Views: 1478
Reputation: 12045
location.replace
initiates an async processJavaScript is single-threaded, not multi-threaded, so it can only process statements sequentially (or synchronously). Contrary to some comments here, this means that two callbacks cannot be executed at the same time. One is being executed first, the other is being executed second.
The issue is that by making a location assignment, an asynchronous process has been initiated by JavaScript in the browser. The browser is now handling the location assignment: making HTTP requests and waiting for a server response before it redirects to the new location.
In the mean time, the JavaScript thread can continue executing the next callback. So, the second alert can appear before the page redirect is completed by the browser.
.done()
conditionally inside your first callbackTo redirect the page in your first success handler without your secondary done()
handler executing, define it conditionally inside your first handler.
function handleLogin() {
if ($("#imalogin").length) {
alert("Your login has expired, please log back in");
// async process initiated
window.location.replace("login.aspx");
// this returns true before the async location redirect completes
return true;
} else {
return false;
}
}
$.get('http://jsonplaceholder.typicode.com/posts/1', function(data, status, jqxhr) {
$("#dbCheck").html(JSON.stringify(data));
// If handleLogin returns false…
if(!handleLogin()) {
// …assign second success handler.
// (This never gets assigned if handleLogin returns true.)
jqxhr.done(function(data) {
alert('second success');
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="imalogin" disabled /><br />
<code id="dbCheck"></code>
Upvotes: 2
Reputation: 79
you need to look at jquery documentation, you passed
function (data) {
$("#dbCheck").html(data);
handleLogin();
}
as $.get second argument , so it is called on ajax success, and again you have used done function with another function as it's argument.
this is from jquery documentation:
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.get( "example.php", function() {
alert( "success" );
})
.done(function() {
alert( "second success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "finished" );
});
Upvotes: 0