1

我最近在 jQuery 中使用 $.Deferred() 进行了一些测试并得到了一个问题。虽然 deferred 和 promise 对于只打算运行一次的 ajaxcall 来说非常有用,但我也有一个表单用于添加需要多次运行 ajax 的新用户。现在这会随着延迟/承诺的二进制(ish)状态而崩溃,因为一旦它们被解决或拒绝,它将保持该状态。所以我的问题是:

-我可以将 deferred 用于将被多次调用的任务吗?- 如果可能,是否建议为此使用 deferred 或者我应该坚持使用旧方法,只使用 $.ajax 的成功/错误回调?

这是我为发布表单而收集的一些代码,一次效果很好,但不是多次。

var submittingUser = new $.Deferred();
var savingUser = submittingUser.pipe(function(data) {
    return $.post('ajax.php', data);
});

$("#add_new_user").click(function() {
    var data = $("#add_user_form").serialize();
    submittingUser.resolve(data);
    return false;
});

savingUser.then(function() {
    //Success
}, function() {
    //Failed
});
4

3 回答 3

2

以这种方式使用 deferred 是没有意义的。一个 deferred 代表一个动作;您不能将其用作事件发射器。当您启动一个异步操作时使用延迟,并且想要在该操作成功或失败时执行某些操作。

$.post()返回一个promise(实际上它返回一个jqXHR实例,但是它实现了promise接口),所以你可以做$.post(...).fail(handleFailure).done(handleSuccess). 但是您不能在每次发生某些事情时使用 deferred 来运行某些代码。

于 2012-05-29T18:53:28.447 回答
2

延迟对象只有一次设计,即使在延迟已解决并触发它们之后,它也允许添加回调。

从您的代码中,似乎并不清楚为什么您不能:

$("#add_user_form").submit( function(e){
    e.preventDefault();
    $.post( "ajax.php", $(this).serialize() ).then( function(){

    }, function() {

    });
});
于 2012-05-29T18:53:52.427 回答
1

我知道这是一个老话题,以前的答案是原始发布者问题的完美解决方案,但我只是遇到了尝试多次解决延迟对象的相同一般问题,所以我想分享一个解决方案。

即使以下是不可能的:

var d = $.Deferred();
d.done(function(text){
   alert('resolved ' + text);
});
d.resolve('Once'); // prints resolved once
d.resolve('Twice'); // this does nothing as done is only fired once

您可以通过使用 jQuery Deferred 对象的进度/通知功能来实现完全相同的效果。做就是了:

var d = $.Deferred();
d.progress(function(text){
   alert('resolved ' + text);
});
d.notify('Once'); // prints resolved once
d.notify('Twice'); // prints resolved twice

通过这种方式,您的延迟对象永远不会真正解决,但它会让您触发尽可能多的异步事件调用。也许以这种方式解决问题并不是最好的软件设计,但我发现它对我刚刚遇到的情况很有用。

于 2015-07-03T14:57:08.623 回答