在开始之前,我想提一下,我对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();
});
});
但是,两个警报都会立即发送,而不是等待请求完成。我尝试过其他方法,但我似乎无法做到这一点。
答案 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错误,页面功能不会丢失。.text()
(而不是.html()
)来设置文本值。