为什么多AJAX查询循环中运行成功两次?两次、AJAX

2023-09-10 14:47:57 作者:木偶人

所以一切正常,问题是,如果冲突被发现,它调用 showInstConflicts(allconflicts,加入); 两次......调试说明它判断为真两次,但我可以' W图出来就可以怎么可能。如果不存在冲突,它不叫 generatePDF()函数两次。

So everything works, the problem is if conflicts are found it calls showInstConflicts(allconflicts, joined); twice... Debugging shows it evaluates true twice but I can't figure out how it possible could. When there are no conflicts, it doesn't call the generatePDF() function twice.

我使用的检查建议的时间表(我们的表单中)对一个教师的现有计划,看是否存在冲突的形式。有时,教师可以有多个会议次为一类,如:

The form I'm using checks the proposed schedule (the form we're on) against an instructor's existing schedule to see if there are conflicts. Sometimes the instructor can have multiple meeting times for one class like:

在每周一三五,一七三零年至1930年,1月12号至5月5号,建筑物房 TR,1200-0100,1月12号至5月5日,建筑物ROOM2

在这种情况下,阿贾克斯检查需要运行两次,以确保两个会议时间没有冲突的。

In that case, the ajax check needs to run twice to make sure that BOTH meetings times have no conflicts.

循环计数的次数与无数据发现,检查,看它是否检查足够的时间( joined.length 这是次次检查数组),如果有至​​少一个时间接收到的数据(即冲突)时。如果找到至少一个成功称之为调用显示功能 showInstConflicts()其中显示了冲突,毕竟检查完(我==次)。

The loop is counting the number of times with nodata found, checking to see if it's checked enough times (joined.length which is an array of meeting times to check) and if there was at least one time when data (aka conflicts) was received. If it finds at least one success call it calls the display function showInstConflicts() which displays the conflicts, after all the checks have finished (i==times).

如果无数据计数

我使用的是个人的jQuery插件 .JSONTable()这只是使一个 $。阿贾克斯呼叫,格式化成基于定义的设置表格。该无数据:时调用Ajax的回报 data.length< 1

I'm using a personal jQuery plugin .JSONTable() which simply makes an $.ajax call and formats it into a table based on defined settings. The nodata: is called when the ajax return data.length < 1.

因此​​,这里的循环:

So here's the loop:

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

}

在$ C $下 $。fn.JSONTable 是在我的网站的 http://curric.uaa.alaska.edu/js/plugins.js ,下半年的文件。

The code for $.fn.JSONTable is on my website http://curric.uaa.alaska.edu/js/plugins.js, second half of the file.

推荐答案

因此​​,它看起来像JSONTable是一个Ajax调用。这意味着它是异步的。因此,您的循环将立即启动所有的异步调用和指数将在在的价值循环结束时的第一个饰面。再加上你的Ajax调用可以完成任意随机顺序。

So, it looks like JSONTable is an Ajax call. That means it's asynchronous. As such, your for loop will immediately launch all the async calls and the index i will be at the value at the end of the loop when the first one finishes. Plus your Ajax calls may finish in any random order.

如果你想看到的正确值i 对应于特定的Ajax调用,那么你就必须把成一个闭合所以它是preserved唯一的每个Ajax调用。

If you want to see the correct value of i that corresponds to that specific Ajax call, then you'd have to put i into a closure so it is preserved uniquely for each Ajax call.

如果你想你的Ajax调用严格按顺序被执行,那么你将不得不重组你如何运行它们(你不能使用直循环)。

If you want your Ajax calls to be executed in strict sequential order, then you will have to restructure how you run them (you can't use a straight for loop).

下面是你将如何preserve的值为每个单独的Ajax调用:

Here's how you would preserve the value of i for each separate ajax call:

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个异步数据和你想要做的这些数据需要看多个异步结果的一些操作,那么最简单的方法是收集所有的数据(通常到一个数组),然后当你把所有的数据处理所有结果一次底。然后,任何相互依存的结果可以看一次。

I'm having a hard time following how exactly you're trying to process all this data. Generally, if you're retrieving N pieces of async data and some operations you want to do on this data needs to look at more than one async result, then the simplest approach is to collect all the data (usually into an array) and then process all the results at once at the end when you have all the data. Then, any inter-result dependencies can be looked at once.

当有多个Ajax调用这样做,通常是最易于使用的承诺,让承诺的基础设施收集所有的结果,并将其交付给您的回调在一个阵列时,所有的Ajax调用完成后(可能使用 Promise.all())。

When doing this with multiple ajax calls, it is generally simplest to use promises and let the promises infrastructure collect all the results and deliver it to your callback in an array when all the ajax calls are done (probably using Promise.all()).