我正在为一些大型查询制作脚本,并避免在php端超时,并为用户提供一些输入,我正在尝试在jquery上进行大部分使用。

因此,它的工作方式如下:首先,用户选择一个记录。当他单击按钮时,我接到ajax调用,以json格式从该记录中获取所需的详细信息。

有了响应,我得到了一个循环,该循环针对第一个调用的每个结果进行ajax调用。

如果我将async设置为false,那么它可以工作,但是由于存在多个ajax调用,浏览器将冻结。那么有没有办法在关闭异步的情况下更新ui?

我的意思是,当我在循环内进行ajax调用时,需要将异步设置为关闭的事实对我来说没有任何意义。它可以同时进行多次调用,我很好,但是除非我将async设置为false,否则为什么它不将当前索引存储在该循环中?它一直使用第一个索引。

    $("#button_copy").live('click', function(){
        $('#button_copy').attr("disabled", true);
        id = $('#select').val();
        $.ajax({
            type: "POST",
            url: "query1.php",
            dataType: 'json',
            async:false,
            cache: false,
            data: 'id=' + id,
            success: function( data ) {
                var total1 = data['records'].length;
                $("#console").append('Total query 1: ' + total1 + '<br />');
                for (var i in data['records']) {
                    $.ajax({
                        type: "POST",
                        url: "query2.php",
                        dataType: 'json',
                        async:false,
                        cache: false,
                        data: 'id=' + data['records'][i].id,
                        success: function( data2 ) {
                            var total2 = data2['records2'].length;
                            $("#console").append('Total of query 2 from ' + data['records'][i].person + ': ' + total2 + '<br />');
                        },
                        error: function(data2) {
                            console.log(data2);
                        }
                    });
                    var percentprogress1 = (i / total1) * 10000;
                    $('#progressbar1').css('width',percentprogress1 + '%');
                }
            },
            error: function(data) {
                console.log(data);
            }
        });
    });

最佳答案

因为尝试在回调中使用i会遇到问题,但是到调用回调时,i不再具有其原始值。您也不应在数组上使用for ... in-仅在对象上使用。

建议不要使用任何for循环,而是在上一个循环完成时触发每个连续的AJAX调用:

$.ajax(...).done(function(data) {

    var all = data.records;
    (function next() {
        var record = all.shift();
        if (record) {
            $.post(...).done(next, function(res) {
                // process inner result
                // update UI, etc
                ...
            });
        }
    })();       // invoke immediately

});


请注意,我使用了“延迟”语法,而不是在两个AJAX调用中传递success:处理程序。

在“伪递归”循环中,请注意,我使用了.done(next, ...),它允许循环在处理当前调用结果的同时并行启动下一个AJAX调用。

10-08 05:30
查看更多