所以我有这个篮子功能,你输入一个作者的名字,然后列出可用的书籍。您可以选择所需内容,然后单击以选择其他作者。当你这样做时,你得到的列表大致如下:
Stephen King
The Stand [remove]
The Talisman [remove]
Pet Sematary [remove]
Terry Pratchett
Mort [remove]
Guards Guards [remove]
在上面的例子中,斯蒂芬·金的书籍已经存放在Session中,而Terry Pratchett的书籍却没有。如果我单击Pratchett书上的删除按钮,一些jquery将隐藏这些。如果我删除了Stephen King的书,那么在jquery隐藏它之前会触发ajax请求将其从Session中删除。
所以我的javascript看起来像这样:
$('.book-remove').click(removeBook);
function deleteFromBasket(bookId) {
var ajaxArgs = { BookId : bookId };
return $.ajax({
// blah blah, no problems here
success: function(e) {
hideRow();
}
});
}
function hideRow(bookId) {
$('.book-id-' + bookId).hide();
}
function removeBook(e) {
e.preventDefault();
if ($(this).hasClass('needs-ajax-call') {
var promise = deleteFromBasket($(this).prop("id").replace("book-id-", ""));
// this is the problem. how do I wait here for the ajax to complete?
}
else
hideRow();
// if i put promise.done(hideRow) up there, it still runs this too soon.
doMoreStuff();
}
答案 0 :(得分:2)
您可以构建所有代码(使用和不使用ajax的代码路径)来使用promises。不需要执行ajax调用的代码可以从已经解析的promise开始,并且两个代码路径将执行相同的序列(一个将更快执行,因为它不必等待对于ajax调用),但两者都将以相同的顺序执行:
你想要在ajax调用之后完成的任何事情只需要移动到promise.then()
处理程序中:
function removeBook(e) {
e.preventDefault();
var promise;
if ($(this).hasClass('needs-ajax-call') {
promise = deleteFromBasket($(this).prop("id").replace("book-id-", ""));
} else {
// get an already resolved promise since no ajax call is required
promise = $.Deferred().resolve();
}
// you can return this promise if you want the calling code
// to be able to know when you're done with everything
return promise.then(function() {
hideRow(bookId); // assumes you've calculated a bookId somewhere
doOtherStuff();
});
}
这样做的好处是,你的代码的lions共享位于一个代码路径而不是两个独立的代码路径中,它解决了你的问题,因为.then()
处理程序中的所有代码在ajax调用之后才会执行完了。
答案 1 :(得分:1)
这是问题的答案以及一些更整洁的DOM / javascript的建议。
首先,让我们确保:
<div>
)class="sessionResultsWrapper"
<div>
)class="otherResultsWrapper"
<li>
和class="entry"
data-bookID="xxxx"
)
现在你处于更好的位置:
$(".sessionResultsWrapper, .otherResultsWrapper").on('click', '.book-remove', function(e) {
e.preventDefault();
var $this = $(this),
promise;
if ($this.parents(".sessionResultsWrapper").length) {
promise = deleteFromBasket($this.closest('entry').data('bookID'));
} else {
promise = $.when();//this is the most compact syntax for a resolved promise
});
// At this point, you have a promise regardless of whether a "session" or "non-session" button was clicked.
// The only difference is that a "non-session" promise will be already resolved, while a "session" promise will be resolved later.
// Because of the way promises work, we can simply chain a .then(fn), which will fire immediately (non session, Terry Pratchett title) or later (when ajax successfully returns, Stephen King title).
promise.then(function() {
$this.closest(".entry").hide();//or, if the entry will never be re-shown then .remove()
doMoreStuff();
});
});
答案 2 :(得分:0)
您可以将doMoreStuff添加为promise的回调。 像这样的东西
function removeBook(e) {
e.preventDefault();
if ($(this).hasClass('needs-ajax-call') {
var promise = deleteFromBasket($(this).prop("id").replace("book-id-", ""));
promise.done(doMoreStuff);
}
else{
hideRow();
doMoreStuff();
}
}