简体   繁体   English

检测AJAX呼叫循环何时完成

[英]Detecting When a Loop of AJAX Calls is Done

I have a web page that can submit an unlimited number of items back to the server for processing. 我有一个网页,可以将无限数量的项目提交回服务器进行处理。

I've decided to submit these items in groups of 25 using AJAX calls to a web service. 我决定使用AJAX调用将这些项目以25个为一组提交给Web服务。 So my loop looks something like this: 所以我的循环看起来像这样:

// Submit elements
for (var i = 0; i < ids.length; i += 25) {

    var productIds = ids.slice(i, Math.min(i + 25, ids.length - 1));

    $.post('/Services/ImportProducts.asmx/ImportProducts', JSON.stringify({ importProductIds: productIds }))
    .done(function (result, statusText, jqxhr) {

        // TODO: Update progress

    })
    .always(function () {
        // TODO: Test for error handling here
    });
}

So far, this seems right. 到目前为止,这似乎是对的。 However, when all processing is complete, I want to refresh the page. 但是,当所有处理完成后,我想刷新页面。 And given the code above, I'm not seeing an easy way to perform a task when the last AJAX call has completed. 鉴于上面的代码,我没有看到在最后一次AJAX调用完成时执行任务的简单方法。

Since $.post() is asynchronous, this loop will complete before the AJAX calls have. 由于$.post()是异步的,因此该循环将在AJAX调用之前完成。 And since the AJAX calls could complete in a different order than they were submitted, I can't simply test for when my last-submitted call is done. 由于AJAX调用可以以与提交时不同的顺序完成,因此我不能简单地测试我上次提交的调用何时完成。

How do I know when this code is done? 我怎么知道这段代码什么时候完成?

You can do this utilizing jQuery's promises . 你可以利用jQuery的承诺来做到这一点。 The general workflow involves you adding each of your promises to an array, then applying that array using jQuery when to execute another callback when all of the promises have returned. 一般工作流程涉及将每个promise添加到数组中,然后使用jQuery应用该数组以便在返回所有promise 执行另一个回调。

Something like this should work: 这样的事情应该有效:

var promises = []
for (var i = 0; i < ids.length; i += 25) {

    var productIds = ids.slice(i, Math.min(i + 25, ids.length - 1));

    var promise = $.post('/Services/ImportProducts.asmx/ImportProducts', JSON.stringify({ importProductIds: productIds }))
    .done(function (result, statusText, jqxhr) {

        // TODO: Update progress

    })
    .always(function () {
        // TODO: Test for error handling here
    });

    promises.push(promise);
}

/*
    Note, the "apply" function allows one to unwrap an array to parameters for a
    function call. If you look at the jQuery.when signature, it expects to be 
    called like: $.when(promise1, promise2, promise3). Using .apply allows you 
    to satisfy the signature while using an array of objects instead.

    See MDN for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
*/
$.when.apply($, promises)
    .done(function() {
        console.log("All done!") // do other stuff
    }).fail(function() {
        // something went wrong here, handle it
    });

You'd do that by pushing all the promises in an array, and using $.when to determine when they are all done 你可以通过推送数组中的所有promises,并使用$.when来确定它们何时完成

var ajaxArr = [];

for (var i = 0; i < ids.length; i += 25) {

    var productIds = {
        importProductIds : ids.slice(i, Math.min(i + 25, ids.length - 1))
    }

    ajaxArr.push(
        $.post('/Services/ImportProducts.asmx/ImportProducts', productIds, function(result, statusText, jqxhr) {
            // TODO: Update progress
        })
    );
}


$.when.apply(undefined, ajaxArr).done(function() {

    window.location.href = 'something'

});

You could set a count that is equal to the number of loops that you have to process and then on returning from the ajax request, decrement the counter and check for it being zero. 您可以设置一个计数,该计数等于您必须处理的循环数,然后从ajax请求返回时,递减计数器并检查它是否为零。 When it reaches zero you can refresh the page 当它达到零时,您可以刷新页面

var remains = ids.length;

// Submit elements
for (var i = 0; i < ids.length; i += 25) {

    var productIds = ids.slice(i, Math.min(i + 25, ids.length - 1));

    $.post('/Services/ImportProducts.asmx/ImportProducts', JSON.stringify({ importProductIds: productIds }))
    .done(function (result, statusText, jqxhr) {

        // TODO: Update progress

    })
    .always(function () {

       // TODO: Test for error handling here

       remains--;
       if ( remains===0 ) {

             // TODO: refresh here
       }
    });
}

Just count how many callbacks are done; 只计算完成了多少次回调; while callbacks are asynchronous, the code is run in a single thread, so they will be called sequentially, and you would be safe to assume that when count == 25 you're done. 虽然回调是异步的,但代码在一个线程中运行,因此它们将按顺序调用,您可以安全地假设当count == 25您已完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM