.each函数完成后重新加载页面

时间:2016-05-10 15:45:52

标签: jquery ajax each

我正在使用带有$.ajax函数的jquery $.each创建一个数组并推送AJAX查询。我希望在完成数组后页面应该刷新,但是当我尝试这样做时,页面之间会刷新。当我使用async:false进行$.ajax查询时,它工作正常,但这会导致性能下降(ajax查询完成所需的时间增加5倍)。有人可以给我指点如何去做,以下是我输入的代码:

$('#update1').click(function()
{
    $.each(testarray,function(k,valu)
    {
        var count = testarray.length;
        var checkloop = k+1;
        var valkor = "/webresources/api/v3/sites/current/pages/" + valu.value;
        var valkis = valu.checkbox;

        var request =
            $.ajax(
            {
                url: valkor,
                processData: false,
                data: JSON.stringify({ "enabled" : valkis }),

                type: "PUT",    
                contentType: "application/json",
                mimeType: "application/json ",
                headers: { "Authorization": $.cookie('access_token') }
            })

        request.done(function(msg)
        {
            console.log("successfully updated"); 
        })

        request.fail(function(jqXHR)
        {
            console.log("Request failed.");
            console.log("Error code: " + jqXHR.status);
            console.log("Error text: " + jqXHR.statusText);
            console.log("Response text: " + jqXHR.responseText);
        })

        request.then(function()
        {
            location.reload(true);
        })
    }) 
})

上面的代码刷新页面而不等待循环完成。我甚至试过循环。请让我知道我错过了什么。

2 个答案:

答案 0 :(得分:2)

您可以使用jQuery .when推迟操作,直到所有 AJAX请求完成后。

这样的事情:

function updateHandler()
{
    var promisesArray = [];
    var successCounter = 0;
    var promise;

    $.each(testarray, function(k, valu)
    {
        var count = testarray.length;
        var checkloop = k+1;
        var valkor = "/webresources/api/v3/sites/current/pages/" + valu.value;
        var valkis = valu.checkbox;

        promise = 
            $.ajax(
            {
                url: valkor,
                processData: false,
                data: JSON.stringify({ "enabled" : valkis }),
                type: "PUT",    
                contentType: "application/json",
                mimeType: "application/json ",
                headers: { "Authorization": $.cookie('access_token') },
            });

        promise.done(function(msg)
        {
            console.log("successfully updated"); 
            successCounter++;
        });

        promise.fail(function(jqXHR) { /* error out... */ });

      promisesArray.push(promise);
    });

    $.when.apply($, promisesArray).done(function()
    {
        location.reload(true);
        console.log("WAITED FOR " + successCounter + " OF " + testarray.length);
    });
}

$('#update1').click(updateHandler);

请参阅$.when的文档。

从jQuery 1.5开始,像$.ajax这样的调用会返回 promise 。这些对于许多不同的事情都很有用(有关承诺的其他有用信息,请参阅this post),但在我们的案例中,我们希望收集承诺,以便为$.when电话提供信息。推迟执行一段代码直到所有AJAX请求都返回响应。

$.each循环中,我们定义$.ajax次调用。一旦定义了每个 - 在每次调用$.ajax之后 - 通过网络发送请求,浏览器将等待响应。此外,我们还会为变量中的每个$.ajax调用收集相关的承诺。在上面的代码中,我们对这些承诺中的每一个做了两件事:1)我们附加了单独的doneerror函数来执行操作 - 特定于单个请求 - 每次通话结束后; 2)我们将承诺存储在promisesArray中,以便我们只有在所有调用完成后才能采取行动。

这里需要注意的一点是,这一行:promise = $.ajax(...不存储结果 - 即AJAX调用的响应 - 它存储与AJAX相关的承诺调用

最后,我们将这些承诺交给$.whendone使用它自己的testarray函数来执行我们想要在所有AJAX调用返回后执行的操作。

上面的解决方案收集了一系列的承诺,因为我的问题假设和promisesArray的使用是我们提前不知道需要多少次AJAX调用。如果确实知道你将使用多少个AJAX调用,我们可以从解决方案中删除$.when( $.ajax( /* args for 1st call */ ).done( /* 1st call success code */ ), $.ajax( /* args for 2nd call */ ).done( /* 2nd call success code */ ), $.ajax( /* args for 3rd call */ ).done( /* 3rd call success code */ ) ).done(function() { location.reload(true); }); ,在3个AJAX调用的情况下看起来像这样:

$.ajax

由于我们可能不知道需要多少次次来电,例如由于用户输入,我们需要收集与未知done次呼叫相关的承诺。

在jQuery支持延迟执行之前 - 在jQuery 1.5之前 - 另一种处理问题的方法只有在这些其他N(通常是AJAX)操作完成之后才采取行动是保持一个大的状态变量:要完成N个动作,您将生成一组N个布尔值。当每个动作完成(返回一个AJAX调用)时,true处理程序会做两件事:1)将它的标志设置为true; 2)检查所有标志是否已设置为apply,然后执行操作,例如重新加载页面。这是因为JavaScript事件队列处理的单线程特性。

此处还有一些事项需要注意:

  • 您需要$.when,因为done期望将延迟作为单独的参数。
  • 我添加了一个在每个AJAX location.reload调用上递增的计数器,如果你注释掉你应该看到的testarray调用 - 假设PUT调用成功 - 那个值是计数器与$.when().done
  • 的大小相匹配
  • 您应该考虑使用$.when().always()$.each之间的区别来确定更适合您自己代码的内容。
  • 我已将$.whenclick循环的设置拉入单独的函数中。这是无关紧要的,您可以将它们保留在原始代码中的id中,它仍然可以使用。
  • 我已经通过添加一个 update1 按钮作为valkor并点击https://httpbin/put作为async: false;网址进行了测试。

一般不要使用{{1}} - 当你发现自己这样做总是备份并寻找另一种方式。 jQuery / JavaScript总是提供一个。

答案 1 :(得分:0)

从AJAX中取出'A'

因为async:false通常是一个坏主意,因为它可能会导致各种各样的阻塞行为,这些行为可能会使您的体验变得非常糟糕,而对于某些请求,它甚至已被完全弃用:

  

从jQuery 1.8开始,使用async:false和jqXHR($ .Deferred)   弃用;您必须使用完整/成功/错误回调。

利用承诺

然而,jQuery支持使用when()then() promise函数,它们允许您存储所有请求,异步执行它们,然后在完成所有请求后执行函数。

您只需将每个请求存储到一个数组中:

// Store your requests
var requestsToProcess = [];

// Build each request
$.each(testarray, function(k, valu){
       // Push this request onto your array
       requestsToProcess.push(
            $.ajax({
                 url: "/webresources/api/v3/sites/current/pages/" + valu.value,
                 processData: false,
                 data: JSON.stringify({ "enabled" : valu.checkbox }),
                 type: "PUT",    
                 contentType: "application/json",
                 mimeType: "application/json ",
                 headers: { "Authorization": $.cookie('access_token') },
                 done: function(msg){
                      console.log("successfully updated"); 
                 },
                 fail: function(jqXHR){
                      console.log("Request failed.");
                      console.log("Error code: " + jqXHR.status);
                      console.log("Error text: " + jqXHR.statusText);
                      console.log("Response text: " + jqXHR.responseText);
                 }
            })
      );
});

// Now that all of your arrays have been added, process them 
$.when(requestsToProcess).then(function(){
       // Everything has been processed, refresh
       location.reload(true);
});