I am building a django project which is a website sending form to server and server responds with the queryset just registered by the form and a message string “Create new event successful.”.
This is code for it:
listevent
is another javascript function which shows the queryset the server just received to “sidebar” div. After that, by document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." );
, appends the message above the result.
Javascript
function makeEvent(event){
event.preventDefault();
var year = event.target.childNodes[3].children[0].value.slice(0,4);
var month = event.target.childNodes[3].children[0].value.slice(5,7);
var day = event.target.childNodes[3].children[0].value.slice(8,10);
var form = $("#makeEventForm");
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize(),
success: function(response){
console.log(response);
listevent(year, month, day);
document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." );
},
error: function(request,status,error){
if (request.status == 599) {
listevent(year, month, day);
document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Error : time overlaps with another event" );
} else {
alert("code:"+request.status+"n"+"message:"+status+"n"+"error:"+error);
}
},
});
}
The problem is, when this makeEvent
function ran and ajax operation successfully done, second line of success function(listevent(year, month, day);
) seems to run later than third line. As a result, “Create new event successful” does not displayed, because listevent
function overwrites all contents in sidebar
div.
So I tried using setTimeout
on the third line, but it seems like does not work at all time. It’ll work if I set the time value sufficiently big, but It looks so bad.
So, my question is:
1. Second line of success function looks like running later than third line, is that right?
2. If so, to third line run after second line ended running, what should I do?
Edit
listevent function
function listevent(year, month, day){
$.ajax({
type: "POST",
url: "{% url 'listevent' %}",
data: {'year':year, 'month':month, 'day':day, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response){
$("#sidebar").attr('year', year);
$("#sidebar").attr('month', month);
$("#sidebar").attr('day', day);
events = JSON.parse(response.events)
var str = "<h4>"+year+"/"+month+"/"+day+"</h4><br>"
if(events.length > 0){
events.forEach(event => str += (event['fields']['start_time']+" - "+event['fields']['title']+"<br>"));
} else {
str += "No events currently."
}
$("#sidebar").html(str);
var btn = $("<button></button>").html("New event");
btn.click(function(){
makeEventClick(day);
});
$("#sidebar").append(btn);
},
error: function(request,status,error){
console.log(error);
},
});
}
2
Answers
Seems to be case of AJAX working out asynchroniosuly.
listevent
is successfully run, but since its AJAX operation the code won’t wait until the response is received, that is left of the success/failure callbacks.So
listevent
is called and AJAX call started and instead of waiting for it to complete, it moves to next line which isdocument.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." );
So my suggestion would be to move this nside
listevent
at the end of the success callback.It’s obvious because inside
listevent()
you are calling an Async AJAX so it’ll run in parallel and obviously will result later than the script response so the script will be executed first, then the ajax response will come and will come into the effect.To fix you can use
async:false
is the ajax method. This will force the script to wait until the ajax returns response. But this is not a good practice.So as a good practice, you can move the next line inside the
listevent()
.