为什么多个ajax查询循环运行两次成功?

时间:2015-06-18 01:01:24

标签: javascript jquery ajax

所以一切正常,问题是如果发现冲突它会调用showInstConflicts(allconflicts, joined);两次...调试显示它评估为真两次但我无法弄清楚它是如何可能的。如果没有冲突,则不会两次调用generatePDF()函数。

我正在使用的表单会根据教师现有的时间表检查建议的时间表(我们所使用的表格),以查看是否存在冲突。有时,教师可以为一个班级设置多个会议时间,如:

  1. MWF,1730-1930,1月12日 - 5月5日,BLDG ROOM
  2. TR,1200-0100,1月12日 - 5月5日,BLDG ROOM2
  3. 在这种情况下,ajax检查需要运行两次以确保两次会议时间没有冲突。

    循环计算找到nodata的次数,检查是否检查了它是否足够(joined.length这是要检查的会议时间数组)以及是否至少有一次收到数据(即冲突)的时间。如果它找到至少一个success调用,它会调用显示冲突的显示函数showInstConflicts(),在所有检查完成后(i==times)。

    如果nodata计数

    我正在使用个人jQuery插件.JSONTable(),只需进行$.ajax调用,并根据已定义的设置将其格式化为表格。当ajax返回nodata:时会调用data.length < 1

    所以这是循环:

    var times = joined.length;
    var nodata = 0;
    var allconflicts = $('<div></div>');
    
    for (i = 0; i < times; i++) {
        var conflicts = $('<div></div>').appendTo(allconflicts);
        //use $.JSONTable plugin (see plugins.js) to check instructor conflicts
        conflicts.JSONTable({
            url: '/ajax/ajaxCSFInstCheck.php',
            options: joined[i],
            noWraps: ['allrows'],
            columns: ['Name', 'Primary', 'Responsible', 'CRN', 'Class', 'Dates', 'Days', 'Times', 'Location', 'XST', 'Web', 'All Meetings'],
            responsive: true,
            success: function () {
                //if conflicts found, show on the final ajax return
                //*** this is evaluating true twice per run ***
                if (i == times && nodata < times) {
                    showInstConflicts(allconflicts, joined);
                }
            },
            nodata: function () {
                //if no conflicts found, make the PDF
                nodata++;
                if (i == times && nodata == times) {
                    generatePDF();
                }
            }
        });
    
    }
    

    $.fn.JSONTable的代码位于我的网站http://curric.uaa.alaska.edu/js/plugins.js,文件的后半部分。

1 个答案:

答案 0 :(得分:2)

因此,看起来JSONTable是一个Ajax调用。这意味着它是异步的。因此,您的for循环将立即启动所有异步调用,并且索引i将在第一个循环结束时处于循环结束时的值。此外,您的Ajax调用可以按任意顺序完成。

如果要查看与该特定Ajax调用相对应的i的正确值,那么您必须将i放入闭包中,以便为每个Ajax保留唯一调用

如果您希望Ajax调用按严格的顺序执行,那么您必须重新调整运行方式(不能使用直接for循环)。

以下是如何为每个单独的ajax调用保留i的值:

var times = joined.length;
var nodata = 0;
var allconflicts = $('<div></div>');

for (var i = 0; i < times; i++) {
    // create closure to capture the value of i
    (function(i) {
        var conflicts = $('<div></div>').appendTo(allconflicts);
        //use $.JSONTable plugin (see plugins.js) to check instructor conflicts
        conflicts.JSONTable({
            url: '/ajax/ajaxCSFInstCheck.php',
            options: joined[i],
            noWraps: ['allrows'],
            columns: ['Name', 'Primary', 'Responsible', 'CRN', 'Class', 'Dates', 'Days', 'Times', 'Location', 'XST', 'Web', 'All Meetings'],
            responsive: true,
            success: function () {
                //if conflicts found, show on the final ajax return
                //*** this is evaluating true twice per run ***
                if (i == times && nodata < times) {
                    showInstConflicts(allconflicts, joined);
                }
            },
            nodata: function () {
                //if no conflicts found, make the PDF
                nodata++;
                if (i == times && nodata == times) {
                    generatePDF();
                }
            }
        });
    })(i);
}

我很难跟踪你是如何准确处理所有这些数据的。通常,如果您要检索N条异步数据,并且您想要对此数据执行的某些操作需要查看多个异步结果,那么最简单的方法是收集所有数据(通常是数组)然后在拥有所有数据时立即处理所有结果。然后,可以一次查看任何结果间依赖关系。

当使用多个ajax调用执行此操作时,通常最简单的方法是使用promises并让promises基础结构收集所有结果,并在完成所有ajax调用后将其传递给数组中的回调(可能使用{{1} })。