Ajax操作比javascript功能运行的时间晚

问题描述 投票:0回答:1

我正在搭建一个django项目,是一个网站向服务器发送表单,服务器响应表单刚刚注册的queryset和一个消息串 "创建新事件成功。"。

这是它的代码。listevent 是另一个javascript函数 将服务器刚刚收到的queryset显示给 "sidebar "div。之后,通过 document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." );在结果上方添加信息。

脚本

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);
                    }
                },
            });
        }

问题是,当这个 makeEvent函数运行,ajax操作成功完成,第二行成功函数(listevent(year, month, day);)似乎比第三行运行得晚。结果,"创建新事件成功 "没有显示,因为 listevent 函数覆盖了所有在 sidebar div。

所以我试着用 setTimeout 在第三行,但它似乎不工作在所有的时间。如果我把时间值设置得足够大,就可以工作,但看起来很糟糕。

所以,我的问题是:1.第二行的成功函数看起来比第三行运行得晚,是这样吗?2. 如果是这样,要第三行运行在第二行结束运行之后,我应该怎么做?


编辑

列名功能

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);
                },
            });
        }
javascript jquery ajax
1个回答
0
投票

很明显,因为在 listevent() 你正在调用一个异步AJAX,所以它会并行运行,显然会比脚本响应晚,所以脚本会先执行,然后ajax响应会来,并会进入效果。

为了解决这个问题,你可以使用 async:false 是 ajax 方法,这将迫使脚本等待 ajax 返回响应。这将强制脚本等待,直到ajax返回响应。但这不是一个好的做法。

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);
            },
        });
    }

所以,作为一个好的做法,你可以把下一行移到下面的 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);
            },
        });
    }

0
投票

似乎是AJAX异步工作的情况。listevent 成功运行,但由于是AJAX操作,代码不会等待直到收到响应,这就是剩下的成功失败回调。

所以 listevent 被调用,AJAX调用开始,而不是等待它完成,它移动到下一行,这就是 document.getElementById("sidebar").insertAdjacentHTML( 'afterbegin', "Create new event successful." );

所以,我的建议是把这个nside listevent 在成功回调结束时。

© www.soinside.com 2019 - 2024. All rights reserved.