【问题标题】:JS for and while loops with jQuery ajax locks up in Chrome带有 jQ​​uery ajax 的 JS for 和 while 循环在 Chrome 中被锁定
【发布时间】:2012-01-20 01:38:51
【问题描述】:

我有一个朋友想要将数据从一个数据库增量移动到另一个数据库,并在执行此操作时显示错误。我觉得我可以通过为他编写一个快速脚本来提供帮助,我在大约一个小时内完成了它,并且在 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 万次插入/更新并将它们分解成更小的块,同步运行查询,并在此过程中更新进度条。

【问题讨论】:

  • Chrome 上的进度条是否以适当的时间间隔更新?
  • 如果我将 alert() 放在进度条的中间,进度条会更新,但浏览器在 while 循环完成之前没有响应。增量是表单中传递的任何内容。因此,如果您可以总计 500 并增加 100,您应该会看到进度条更新 5 次 @20%。适用于 FF 和 Opera,而不是 Chrome。
  • 所以您要求浏览器尽可能快地执行“总”获取?您可能只需要错开或计时,以免浏览器不堪重负。
  • (已删除评论 - 错过了async: false。)
  • 为了测试,我在函数中有 sleep(1) 替换任何实际工作并尝试只执行总共两个循环,所以第一次运行会将进度条更新为 50,然后是 100%,它仍然在 FF 和 Opera 中运行良好,但不是 Chrome。

标签: php javascript jquery ajax google-chrome


【解决方案1】:

好吧,您使用的是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();
    }
});

【讨论】:

  • 谢谢,我会尝试修改它以使其正常工作。仅供参考,增量和进度是 mysql 中的限制和偏移。 Total 是我们想要的总记录。 php 页面上的函数将处理比显示的更多的内容,但我想尽可能简化示例,以找出导致问题的原因。
【解决方案2】:

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

来自jQuery doc

异步布尔

默认:真

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

文档可能会显示为“可能”,因为跨浏览器的行为不一致。如果您想强制页面重绘,您必须让 JavaScript 执行定期终止。要做到这一点,不要使用 while 循环,而是调用“嵌套”setTimeout()s 或使用异步请求,并在上一个请求的回调中调用下一个请求。

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 2012-09-10
    • 2012-03-06
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2015-02-08
    • 2016-03-06
    • 1970-01-01
    相关资源
    最近更新 更多