skip to Main Content

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 makeEventfunction 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


  1. 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 is document.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.

    Login or Signup to reply.
  2. 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.

    function listevent(year, month, day){
            $.ajax({
                type: "POST",
                url: "{% url 'listevent' %}",
                async:false, // added
                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);
                },
            });
        }
    

    So as a good practice, you can move the next line inside the listevent().

    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);
                    document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." ); // Added
                },
                error: function(request,status,error){
                       console.log(error);
                },
            });
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search