如何在循环中链接异步ajax函数

时间:2015-05-18 07:04:25

标签: jquery ajax

我想链接一个在循环中多次调用的异步ajax函数。为什么?因为该功能是上传文件,但我希望它能够连续上传文件而不是一次上传所有文件。我不想使用async false,因为我希望在DOM上更新进度。

for (var i = 0; i < files.length; i++) {
         var fd = new FormData();

         fd.append('file', files[i]);
         fd.append('galleryid', galleryid);

        sendFileToServer(fd); //chain this function call
    }

function sendFileToServer(formData)
{
    var uploadURL ="includes/ajax/images/uploadImagePage.php"; //Upload URL
    var extraData ={}; //Extra Data.
    return jqXHR=$.ajax({
            xhr: function() {
            var xhrobj = $.ajaxSettings.xhr();
            if (xhrobj.upload) {
                    xhrobj.upload.addEventListener('progress', function(event) {
                        var percent = 0;
                        var position = event.loaded || event.position;
                        var total = event.total;
                        if (event.lengthComputable) {
                            percent = Math.ceil(position / total * 100);
                        }
                        //Set progress
                       $('#uploadImageResponse').html(percent+'%');
                    }, false);
                }
            return xhrobj;
        },
    url: uploadURL,
    type: "POST",
    async:true,
    contentType:false,
    processData: false,
        cache: false,
        data: formData,
        success: function(data){
            status.setProgress('Upload completed. 100%.');

        }
    }); 


}

我不明白jquery延迟对象是如何工作的。

2 个答案:

答案 0 :(得分:2)

有许多不同的方法可以像这样序列化多个请求。这是使用手动迭代而不是for循环的一种方式,因此您只能在前一个迭代完成时前进到下一次迭代。

手动迭代

function sendAllFiles(files) {
    var index = 0;

    function next() {
        var fd;
        if (index < files.length) {
            fd = new FormData();
            fd.append('file', files[index]);
            fd.append('galleryid', galleryid);
            ++index;
            // send this file and when done, do the next iteration
            sendFileToServer(fd).then(next);
        } else {
            // all files are done now
        }
    }
    // start the first iteration
    next();
}

使用.reduce()

链接承诺

而且,这是使用.reduce()和链式承诺的不同设计模式:

files.reduce(function(p, item) {
    return p.then(function() {
        var fd = new FormData();
        fd.append('file', item);
        fd.append('galleryid', galleryid);
        return sendFileToServer(fd);
    });
}, $.Deferred().resolve()).then(function() {
    // all files are done now
});

答案 1 :(得分:0)

你总是可以尝试这个......

function step1() { 
       updatePercentage(); 
       $.ajax({ ... , // fill in these details
                  success: step2 }); }
function step2(data) { 
      updatePercentage(); 
       $.ajax({ ... ,
                success: step3 });
}
function step3(data) { 
       updatePercentage(); 
       $.ajax({ ... ,
                success: step4?? });
}

这可以重构。我会留给你的,但是:)