JS for和while循环使用jQuery ajax锁定在Chrome中


JS for and while loops with jQuery ajax locks up in Chrome

我有一个朋友想要将数据从一个数据库增量移动到另一个数据库,并在执行此操作时显示错误。我觉得我可以帮他写一个快速的脚本,我在大约一个小时内完成了它,在Opera和Firefox中运行良好(用蜻蜓和萤火虫测试)。当他在Chrome中尝试时,浏览器会锁定,直到for或while循环完成,并且需要相当长的时间才能完成。以下是我的代码(没有读取json的错误捕获部分):

jQuery.noConflict();
jQuery('#myForm').submit(function(form) {
    form.preventDefault();
    var increment = (jQuery("input#increment").val())*1;
    var total = jQuery("input#total").val();
    var progress = 0;
    jQuery("#progressbar").progressbar({value: 0});
    //for (progress = 0; progress < total; progress = progress + increment)
    while (progress < total)
    {
        jQuery.ajax({
            url: 'progressBarAjax.php',
            type: "POST",
            async: false,
            dataType: "json",
            data: {
                ajax: 'goAjax',
                total: total,
                increment: increment,
                progress: progress
            },
            success: function(data){
                jQuery("#progressbar").progressbar({value: data.value});
            }
        });
        progress = progress + increment;
    }
});

此外,为了进一步参考,在调试期间删除了捕获错误的代码,data.value=floor(($progress/$total)*100)。你也可以看到我已经尝试了一段时间,在Opera和Firefox中都能很好地工作,但在Chrome中不行。

知道为什么会发生这种行为对于未来的项目来说是件好事,但我也想把它写得正确。目标是进行20万次插入/更新,并将其分解为更小的块,同步运行查询,并在此过程中更新进度条。

好吧,您使用的是async:false,所以在发出请求时浏览器会锁定。如果增量为0.,则while也可以进入无限循环

我认为你实际上想查询服务器,如果服务器回来后在json响应中说还没有完成,那么再次查询,直到它说已经完成

var increment, total, progress;
function getProgress(){
    jQuery.ajax({
        url: 'progressBarAjax.php',
        type: "POST",
        async: true,
        dataType: "json",
        data: {
            ajax: 'goAjax',
            total: total,           // Obviously, I don't know what these
            increment: increment,   // do on your server, so I've kept
            progress: progress      // them here.
        },
        success: function(data){
            // Assuming data.value is the progress from 1-100?
            // otherwise, figure out the progress from the data response
            progress = data.value;
            jQuery("#progressbar").progressbar({value: progress});
            if(progress < 100){
                getProgress();
            }else{
                // All done
                alert('done'); 
            }  
        }
    });
}
jQuery('#myForm').submit(function(form) {
    form.preventDefault();
    // Only go if we aren't currently.
    if(progress == null || progress == 100){
        increment = (jQuery("input#increment").val())*1;
        total = jQuery("input#total").val();
        progress = 0;
        getProgress();
    }
});

如果您正在执行同步AJAX请求,特别是如果您正在按顺序执行多个请求,则浏览器锁定是一种预期行为。

来自jQuery文档:

异步布尔

默认值:真

默认情况下,所有请求都是异步发送的(即,默认情况下设置为true)。如果需要同步请求,请将此选项设置为false。跨域请求和数据类型:"jsonp"请求不支持同步操作。请注意,同步请求可能会暂时锁定浏览器,从而在请求处于活动状态时禁用任何操作。

文档读起来可能是"may",因为浏览器之间的行为不一致。如果要强制重新绘制页面,则必须允许JavaScript执行周期性终止。为了实现这一点,不使用while循环,而是调用"嵌套的"setTimeout() s或使用的异步请求,并在上一个请求的回调中调用下一个请求。