【问题标题】:AJAX -- Multiple concurrent requests: Delay AJAX execution until certain calls have completedAJAX -- 多个并发请求:延迟 AJAX 执行,直到某些调用完成
【发布时间】:2014-09-09 09:12:58
【问题描述】:

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

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

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

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

这里的主要问题是更新视图,尽管我也发现了一些由于并发数据库事务而导致的失败调用(尤其是在依次选择“保存”和“删除”时)。任何关于该问题的反馈——请求不要“等待”同一行再次准备好——也将受到赞赏,但这不是我的问题。

我有一个updateTemplate(data, day) 函数,它在我的任一函数saveRecord()deleteRecord()pasteRecords()makeEditable()(撤消保存)中调用相应的ajax 调用。这是 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

现在,当我在很短的时间间隔内重复单击create 时会发生什么,由于异步调用,一些create(或其他)操作同时执行。问题是updateTemplate 只是从响应中呈现数据;要呈现的数据在create 控制器操作中收集。但是“最后一个”请求动作只找到自己创建的对象。我认为这是因为create 动作是同时运行的

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

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

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

【问题讨论】:

  • 在得到响应之前阻止按钮怎么样(+ 显示任何预加载器)?我不明白您想在其他部分中说什么您的代码出了什么问题...
  • 您好,感谢您的回复。这是个好主意,但您也可以使用快捷方式。我只是想知道这是否是更新视图的不好方法,或者是否可以改进。该工具的一半存在于遗留代码中,我试图在不使用合适的 JavaScript 框架从头开始重新启动的情况下完成这项工作。我基本上现在出了什么问题,我似乎没有找到任何关于如何处理许多并发 AJAX 调用的信息。
  • 您也可以阻止快捷方式...我想您调用按钮单击和快捷方式一个功能,在此功能中您可以添加一些条件来检查是否有正在运行的呼叫(设置running = true 通话前和 onSuccess running = false,就是这样)
  • 我想我明白你的意思了。我已经尝试将全局变量 noAjaxRunning 用于其他想法。但这不与使用同步调用基本相同吗?基本上我不想阻止任何东西。我希望用户能够同时执行 100 个请求,我只想确保在触发下一个 ajax 调用之前将该行保存在数据库中——但我不想要同步调用(如果不可避免的)!该脚本不应停止,因为我知道用户不会喜欢它。不可能?
  • 脚本不会停止。您只会阻止会导致下一次 AJAX 调用的函数,仅此而已。所有其他操作均不受影响。

标签: javascript jquery ajax grails httprequest


【解决方案1】:

this Stackoverflow answer 的帮助下,我找到了一种方法来确保 ajax 调用(在最后执行的 javascript 函数中)始终以最新模型进行响应。基本上,如果之前已启动“关键”AJAX 请求但尚未完成,我会将包含 AJAX 调用的 javascript 函数放入等待队列中。

为此,我定义了函数doCallAjaxBusyAwareFunction(callable),它在执行callable 函数之前检查全局变量Global.busy 是否为“真”。如果为真,该函数将再次执行,直到Global.busy 变为false,最终执行该函数——从 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——例如通过deletes 而函数xyz 收集DOM 数据。但是当函数执行时,还有Global.busy === true直到ajax调用完成。

从“忙碌感知”函数触发 ajax 调用:

doCallAjaxBusyAwareFunction(function(){
    //collect DOM data

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

....或者从一个“忙碌感知”函数触发一个 ajax 调用,该函数本身也被标记为关键(基本上我主要使用它):

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-26
    • 2016-07-03
    • 2011-10-17
    • 2015-01-02
    • 1970-01-01
    • 2014-03-15
    • 2016-07-22
    • 2016-09-08
    相关资源
    最近更新 更多