2

我正在编写一个 jQuery UI 插件。在该插件内部,当发生操作时,我将调用插件选项之一作为回调。回调完成后,我想运行一些清理代码。

更具体地说,我的插件使用可拖放的 jQuery UI。在 droppable drop上,我调用了选项中定义的函数update。在调用update之后,这是一个 AJAX 调用,我想执行一些清理。我不希望插件的用户被要求执行此清理调用;我希望更新 AJAX 方法成功后自动进行清理调用。

我认为在这里使用 jQuery 的 Deferred 是有意义的。这是插件的drop实现的一些代码:

self.connectedLists = $(self.options.connectWith)
    .not(self.list)
    .droppable({
        hoverClass: 'ui-selectablelist-active',
        drop: function(e, ui) {
            var sender = $(ui.draggable).closest('ul'),
                deferred = self.options.update.call(self, e, {
                    sender: sender,
                    receiver: $(this),
                    items: selectedItems
                });

            deferred.then(function () {
                self.removeSelectedItems();
            });
        }
    });

插件实现者的代码如下所示:

update: function (e, ui) {
    var self = this;
    return $.post(url, 
            {                 
                // some data                         
            })
            .done(function (data) {
                console.log('updated!');
            });
}

我将 AJAX 调用作为对drop回调的承诺返回。在 drop 回调中,我想始终执行清理操作removeSelectedItems,所以我使用了 .then() 函数。它似乎没有运行。

这种模式听起来是不是一个好主意。任何人都可以帮我做这个设计吗?为什么我的 done 函数没有在drop回调中运行?

4

1 回答 1

2

而不是使用.then,使用.always

.then用于向延迟对象添加回调:

deferred.then(donecallbacks,failcallbacks)

尝试:

self.connectedLists = $(self.options.connectWith)
    .not(self.list)
    .droppable({
        hoverClass: 'ui-selectablelist-active',
        drop: function(e, ui) {
            var sender = $(ui.draggable).closest('ul'),
                deferred = self.options.update.call(self, e, {
                    sender: sender,
                    receiver: $(this),
                    items: selectedItems
                });

            deferred.always(function () {
                self.removeSelectedItems();
            });
        }
    });

更新:

由于开发人员将指定更新函数,因此开发人员总是有可能无法正确地将延迟对象返回给您。在这种情况下,您应该检查并抛出异常。

self.connectedLists = $(self.options.connectWith)
    .not(self.list)
    .droppable({
        hoverClass: 'ui-selectablelist-active',
        drop: function(e, ui) {
            var sender = $(ui.draggable).closest('ul'),
                deferred = self.options.update.call(self, e, {
                    sender: sender,
                    receiver: $(this),
                    items: selectedItems
                });
            if (deferred.always) {
                deferred.always(function () {
                  self.removeSelectedItems();
                });
            }
            else {
                $.error("Update must return a deferred object.");
            }
        }
    });
于 2012-01-12T20:43:50.997 回答