jquery在ajax完成之前等待动画完成

时间:2016-11-02 09:30:54

标签: jquery ajax jquery-animate progress-bar jquery-deferred

我上传了一个电子表格,将数据导入我的数据库,在插入之前,我对每个值运行一些服务器端验证。

我使用jquery ajax将文件上传到服务器,然后以多维数组的形式获得处理数据的响应

var errored = false;
var items = [];
var width;
var percent;

$("#uploadForm").ajaxForm({
    dataType: 'json',
    beforeSubmit: function() {
        errored = false;
        width = 0;
        percent = 0;
    },
    beforeSend: function() { //before sending form
        $('#upload-progress').show();
    },
    uploadProgress: function(event, position, total, percentComplete) { //on progress
        $('#load').width(percentComplete + '%') //update progressbar percent complete
        $('#load').html(percentComplete + '%'); //update status text
    },
    success: function(response) {
        var size = Object.keys(response.items).length + 1;
        //this will trigger the first callback.
        var base = $.when({});
        var promises = [];

        percent = 100 / Object.keys(response.items).length;

        $('#validate-progress').show();
        $('#UploadButton').html('<i class="fa fa-cog fa-spin fa-fw"></i> Validating Data');

        $.each(response.items, function(key, item) {
            var last = (key == size) ? true : false;

            promises.push(base = base.then(getAjaxDeferred(key, item, last)));
        });
    },
    complete: function() {
        $('#load').width('0%'); //update progressbar percent complete
        $('#upload-progress').hide();
        $(this).clearForm();
    }
});

然后我循环遍历数组的每一行,并将其传递给jquery函数,该函数使用ajax并将其推迟直到它完成,然后再发送下一行。

function getAjaxDeferred(row, item, last) {
    return function() {
        // wrap with a deferred
        var defer = $.Deferred();
        $.ajax({ 
            url: 'path/to/file', 
            method: 'POST',
            data: {
                row: row,
                item: item
            },
            dataType: 'json',
            success: function(response) {

                $('<p>' + response.description + ' <i class="fa fa-check"></i></p>').appendTo('#inserted-rows');
                items.push(response.item);                

                if(last) {
                    $('<p class="last-insert">All done!!</p>').appendTo('#inserted-rows');

                    if(errored) {
                        $('#myModal-errors').modal('show');
                    }
                }
                width = width + percent;
                $('#validating').width(width + '%').html((Math.round(width * 10) / 10).toFixed(0) + '%');
                $('#inserted-rows').show().animate({ scrollTop: $('#inserted-rows').prop("scrollHeight") - $('#inserted-rows').height() }, 'fast');
            },
            complete: function() {
                // resolve when complete always.  Even on failure we 
                // want to keep going with other requests
                defer.resolve();
            }
        });
        // return a promise so that we can chain properly in the each 
        return defer.promise();
    };
}

一切都在我的开发服务器上完全正常工作(因为它比生产慢很多),一行发送到函数,它在服务器上验证,添加对输出div的响应,通过a更新进度条宽度百分比,如果它是最后一行,如果发现任何错误,将显示一个模态。

我在生产服务器上遇到的问题是因为它太快了,进度条比动画更快地更新,因此它会立即完成,并且在动画完成之前会出现模态。

我尝试在动画中添加一个完整的:function(),该动画停止了模态的显示,直到最后一行被处理,但它没有帮助进度条更新得太快。

如何在更新宽度之前将进度条延迟等待动画完成,并使模态等待直到最后一行被处理?

1 个答案:

答案 0 :(得分:1)

animate()之前尝试stop(false, true)

$('#inserted-rows').show().stop(false, true).animate({.... 

这会在开始下一个动画之前立即完成当前动画。否则,动画将排队并一个接一个地运行直到完成。