等待多个$ .getJSON完成

时间:2016-11-14 15:49:08

标签: javascript jquery promise

在开始之前,我想提一下,我对JavaScript中的promises / deferred对象没有多少经验。

我想要实现的目标是,当用户点击按钮时,它会运行多个$.getJSON请求,处理响应并相应地更新页面。

我还需要在完成所有这些请求后通知用户,这里是我处理我所谈到的第一部分的connect方法:

function connect(row) {
    return new Promise(function(resolve, reject) {
        var trees = $("#selectedTree").val();
        var employee_id = row.attr("rel");

        var columns = row.children();
        var emailColumn = $(columns[1]);
        var firstNameColumn = $(columns[2]);
        var lastNameColumn = $(columns[3]);
        var jobTitleColumn = $(columns[4]);
        var statusColumn = $(columns[5]);
        var actionsColumn = $(columns[6]);

        actionsColumn.html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>");
        $.getJSON("functions/connect_with.php", {
            employee_id: employee_id,
            trees: trees
        }, function(response) {
            emailColumn.html(response.message.person.email);
            actionsColumn.html("<i class='text-success fa fa-check'></i>");
            if(response.success) {
                firstNameColumn.html(response.message.person.name.givenName);
                lastNameColumn.html(response.message.person.name.familyName);
                jobTitleColumn.html(response.message.person.employment.title);
            }
            statusColumn.html("<i class='text-success fa fa-sitemap'></i>");
            resolve(true);
        });
    });
}

当用户点击所述按钮时会发生这种情况:

    $("#connectAll").click(function() {
        alert("OFF WE GO");
        $(this).hide();
        var methods = [];
        $(".staffMember input:checked").each(function(index, checkbox) {
            checkbox = $(checkbox);
            var row = checkbox.parents("tr");
            methods.push(connect(row));
        });
        $.when.apply($, methods).then(function () {
            alert("WE DID IT MOM");
            $("#connectAll").show();   
        });
    });

但是,两个警报都会立即发送,而不是等待请求完成。我尝试过其他方法,但我似乎无法做到这一点。

2 个答案:

答案 0 :(得分:2)

而不是致电apply使用Promise.all

执行一系列promises并在完成所有操作后返回。

所以你的代码会变成:

$("#connectAll").click(function() {
  alert("OFF WE GO");
  $(this).hide();
  var methods = [];
  $(".staffMember input:checked").each(function(index, checkbox) {
    checkbox = $(checkbox);
    var row = checkbox.parents("tr");
    methods.push(connect(row));
  });
  Promise.all(methods).then(values => {
    alert("WE DID IT MOM");
    $("#connectAll").show();   
  }).catch(reason => {
    alert("MOM, SOMETHING WENT WRONG");
  });
});

答案 1 :(得分:1)

您根本不需要在代码中使用Promise - 而且until all browsers support native promises,除非您要加载自己的承诺库,否则我会建议不要使用它。

但主要原因是jQuery为这项任务实现了足够好的承诺。每个jQuery Ajax函数都返回一个promise,你可以直接使用它们。

以下是我编写代码的方法:

function connect($row) {
    var columns = $row.children("td");
    $(columns[6]).html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>");

    return $.getJSON("functions/connect_with.php", {
        employee_id: $row.attr("rel"),
        trees: $("#selectedTree").val()
    }).done(function (response) {
        $(columns[1]).text(response.message.person.email);
        if(response.success) {
            $(columns[2]).text(response.message.person.name.givenName);
            $(columns[3]).text(response.message.person.name.familyName);
            $(columns[4]).text(response.message.person.employment.title);
        }
        $(columns[5]).html("<i class='text-success fa fa-sitemap'></i>");
    }).always(function () {
        $(columns[6]).html("<i class='text-success fa fa-check'></i>");
    });
}


$("#connectAll").click(function() {
    $(this).hide();

    var calls = $(".staffMember input:checked").map(function () {
        return connect( $(this).parents("tr") );
    }).toArray();

    $.when.apply($, calls)
    .fail(function (jqXhr, status, error) {
        // display or handle the error
    })
    .always(function () {
        $("#connectAll").show();
    });
});

附注:

  • 您应该实现错误处理程序(.fail(...)
  • 删除微调器或恢复按钮的代码应该位于.always()处理程序中,这样由于间歇性的Ajax错误,页面功能不会丢失。
  • 你应该使用jQuery的.text()(而不是.html())来设置文本值。