AJAX - 多个并发请求:延迟AJAX执行,直到某些调用完成

时间:2014-09-09 09:12:58

标签: javascript jquery ajax grails httprequest

我目前正在开发基于网络的时间跟踪软件。我正在使用grails进行开发,但这个问题仅与javascript和异步请求有关。

时间跟踪工具应允许用户选择当月的一天每天创建一个或多个活动保存一整天< / em>的。必须将每个活动分配给项目和合同。

选择“保存”后,部分日期将保存到数据库中,计算小时数并在页面底部更新表格,并显示用户每月工作时间的概览。

现在我的问题:可能有很多AJAX请求。患者用户可能只需单击“创建活动”按钮一次,并等待它创建。然而,其他人可能只是一直点击直到发生事情。

这里的主要问题是更新视图,虽然我也因为并发数据库事务而识别出一些失败的调用(特别是在顺序选择“save”和“delete”时)。关于这个问题的任何反馈 - 请求不要“等待”同一行再次准备好 - 也会被贬低,但这不是我的问题。

我有一个updateTemplate(data, day)函数,该函数在我的函数saveRecord()deleteRecord()pasteRecords()makeEditable()中的各个ajax调用的onSuccess上调用(撤消保存)。以下是jquery中的示例AJAX调用:

$.ajax({
    type: "POST",
    url: "${g.createLink(controller:"controller", action:"action")}",
    data: requestJson,
    contentType:"application/json; charset=utf-8",  
    async: true,
    success: function(data, textstatus) {updateTemplate(data["template"], tag); updateTable(data["table"]);},
}); 

在控制器操作中,JSON对象呈现为响应,包含键templatetable。每个键都使用g.render将模板呈现为分配给它的String。

现在,当我在非常短的intervalls中反复点击create时会发生什么,由于异步调用,一些create(或其他)动作会同时执行。问题是updateTemplate只是从repsonse渲染数据;要渲染的数据收集在create控制器操作中。但“最后”请求操作仅查找自己创建的对象。我认为这是因为create动作同时运行

我认为有一些东西我要么过于复杂,要么在使用动态刷新的页面时做一些本质上错误的事情。我发现唯一有帮助的是同步调用,这有效,但用户体验很糟糕。我有什么选择才能使这项工作?这真的是它还是我只是在寻找错误的方法? 如何让这一切变得更加强大,以便不耐烦的用户无法破解我的代码?

*********编辑:********

我知道我可以阻止按钮或键盘快捷键,使用同步调用或类似的东西来避免这些问题。但是,我想知道是否可以通过提交多个AJAX请求来解决它。因此,用户应该能够继续添加新活动,尽管它们不会立即显示。无论如何,有一个微调器供反馈。我只是想以某种方式确保在“最后一次”AJAX请求被触发之前,数据库是最新的,以便控制器操作将使用具有正确对象的最新gsp模板进行响应

1 个答案:

答案 0 :(得分:0)

this Stackoverflow answer的帮助下,我找到了一种方法来确保最后执行的javascript函数中的ajax调用始终以最新模型响应。基本上,我把包含AJAX调用的javascript函数放在一个等待队列中,如果&#34; critical&#34; AJAX请求之前已经启动但尚未完成。

为此,我定义了函数doCallAjaxBusyAwareFunction(callable),用于检查全局变量Global.busy是否为真&#39;在执行callable函数之前。如果确实如此,则该函数将再次执行,直到Global.busyfalse,才能最终执行函数 - 从DOM收集数据 - 并激活AJAX请求。

全局变量的定义:

var Global = {
    ajaxIsBusy = false//,
    //additional Global scope variables
};

函数doCallAjaxBusyAwareFunction的定义:

function doCallAjaxBusyAwareFunction(callable) {
        if(Global.busy == true){
           console.log("Global.busy = " + Global.busy + ". Timout set! Try again in 100ms!!");  
           setTimeout(function(){doCallAjaxBusyAwareFunction(callable);}, 100);
        }     
        else{                
            console.log("Global.busy = " + Global.busy + ". Call function!!");   
            callable();             
        }
    }

要将包含ajax的函数标记为关键,我让它在开始时设置Global.busy = true并在AJAX完成时设置Global.busy = false。示例电话:

function xyz (){
    Global.busy = true;
    //collect ajax request parameters from DOM

    $.ajax({
        //desired ajax settings
        complete: function(data, status){ Global.busy = false; }
    }

由于Global.busy一开始就设置为true,因此无法操纵DOM - 例如函数delete收集DOM数据时xyz s。但是当执行该函数时,在ajax调用完成之前仍然存在Global.busy === true

从&#34;忙碌的&#34;发起ajax呼叫。功能:

doCallAjaxBusyAwareFunction(function(){
    //collect DOM data

    $.ajax({/*AJAX settings*/});
});

....或者从#34;忙碌的&#34;中拨打ajax电话。功能也标记为关键(基本上我主要使用它):

doCallAjaxBusyAwareFunction(function(){
    Global.busy = true;
    //collect DOM data

    $.ajax({
        //AJAX SETTINGS
        complete: function(data, status){ Global.busy = false; }
    });
});

欢迎反馈和其他选择,特别是如果这种方法是不好的做法。我真的希望有人找到这篇文章并对其进行评估,因为我不知道是否应该这样做。我暂时还没有回答这个问题。