等到未知数量的ajax请求完成

时间:2019-07-13 13:48:17

标签: javascript jquery ajax

我正在将文档列表上载到服务器,并且对于每个文档,我都会启动ajax请求,但是请求的数量是未知的(取决于要上载的文档的数量)。上传所有文档(完成所有ajax请求)后,如何向用户显示消息。

$.each(files,function(idx,elm){
                    let formData = new FormData();
                    let ID = '_' + Math.random().toString(36).substr(2, 9);
                    formData.append('document_id', ID);
                    formData.append('file-doc', elm);
                    $.ajax({
                    url: "http://127.0.0.1:5000/add_multiple_docs",
                        type: 'POST',
                        data: formData,
                        cache: false,
                        contentType: false,
                        processData: false,
                        beforeSend: function (xhr, settings) {
                            function getCookie(name) {
                                var cookieValue = null;
                                if (document.cookie && document.cookie !== '') {
                                    var cookies = document.cookie.split(';');
                                    for (var i = 0; i < cookies.length; i++) {
                                        var cookie = jQuery.trim(cookies[i]);
                                        // Does this cookie string begin with the name we want?
                                        if (cookie.substring(0, name.length + 1) === (name + '=')) {
                                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                                            break;
                                        }
                                    }
                                }
                                return cookieValue;
                            }

                            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                                // Only send the token to relative URLs i.e. locally.
                                xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
                            }
                        },
                        success: function (data) {
                            alert(data);
                        },
                        failure: function (request) {
                            console.log(request);
                        },
                        error: function (jqXHR, exception) {
                            console.log("error add document");
                            let msg = '';
                            if (jqXHR.status === 0) {
                                msg = 'Not connect.\n Verify Network.';
                            } else if (jqXHR.status === 404) {
                                msg = 'Requested page not found. [404]';
                            } else if (jqXHR.status === 500) {
                                msg = 'Internal Server Error [500].';
                            } else if (exception === 'parsererror') {
                                msg = 'Requested JSON parse failed.';
                            } else if (exception === 'timeout') {
                                msg = 'Time out error.';
                            } else if (exception === 'abort') {
                                msg = 'Ajax request aborted.';
                            } else {
                                msg = 'Uncaught Error.\n' + jqXHR.responseText;
                            }
                            console.log(msg)
                        }
                    });
                });                
            }

3 个答案:

答案 0 :(得分:1)

要实现所需的功能,可以将从$.ajax()返回的所有jqXHR对象放在一个数组中,该数组可以apply()$.when()。在所有这些承诺都解决之后,您便可以执行所需的任何逻辑。试试这个:

var promises = files.map(function(elm) {
  // setup formData...

  return $.ajax({
    url: "http://127.0.0.1:5000/add_multiple_docs",
    // ajax settings...
  });
});

$.when.apply($, promises).done(function() {
  console.log('all requests complete, do something here...');
});

然而,绝对值得注意的是,在循环中发送AJAX请求不是可扩展的模式。将所有文件和相关数据聚合到一个AJAX请求中,然后在服务器上处理一次,将是一个更好的主意。

答案 1 :(得分:1)

首先,您知道要上传多少个文件,所以您知道要执行多少个ajax请求。 (每个文件1个请求)

因此,在您的$.each()被解雇之前,您的大小为files

let count = $(files).size();

$.each(files,function(idx,elm){
/*your code with requests*/
}

现在,在每个ajax请求均未触发后,递减count。在successfailure方法中递减,因为无论成功与否,它都不会消光。并检查是否count === 0。如果它是0,那么您知道所有ajax都已完成。

$.ajax({
/*your other settings*/
    success: function (data) {
        alert(data);
        count--;

        doSomething(count);
    },
    failure: function (request) {
        console.log(request);
        count--;

        doSomething(count);
    },
});

function doSomething(count){
    if(count === 0){
        /*stuff you wannna do after all ajax requests are done*/
    }
}

我现在还没有做那么多ajax,所以我不确定failure上是否也触发了error,但是如果不能,还可以添加count--和if也会出错。

答案 2 :(得分:0)

一个非常有趣的问题。

当尝试从youtube API获取数据时,我遇到了类似的问题,该API仅返回最多50个项目的结果集。

为解决此问题,我使用了一个接受回调的递归函数,在基本情况下(在我的情况下,当没有nextPageToken时),我调用了回调函数。

在$ .ajax请求的成功处理程序中触发了递归。

    function fetchVideos(nextPageToken, callback) {
        if (nextPageToken === null || nextPageToken === undefined) {
            callback(null);
            return;
        }

        $.ajax(requestURI + `&pageToken=${nextPageToken}`, {
            success: (data) => {
                // use data somehow?
                fetchVideos(data.nextPageToken, callback);
            },

            error: (err) => {                    
                callback(err);
            }
        })
    }

    fetchVideos("", (err) => {
        if (err) {
            console.log(err.responseJSON);
            return;
        }
        updateUI();
    })

当响应中不再有nextPageToken时,它将触发if语句。我认为它可以同步吗?因为我需要nextPageToken才能执行下一个请求。

我知道这不是最适合您的情况,但我是根据标题(即我进入此页面的方式)回答的:)