【问题标题】:Backbone - prevent deferred execution after view is removedBackbone - 删除视图后防止延迟执行
【发布时间】:2017-03-25 13:01:21
【问题描述】:

我有一个主视图,其中有一个框,其中包含您可以在它们之间切换的子视图

fetch ajax 调用成功后,主视图上会显示一个“成功”的 div。

我面临的问题是,当我在子视图之间切换时,前一个视图提取的延迟承诺仍然会被执行并显示“成功”div。

这是我的代码:

this.model.fetch().done(function() {
  $('#success').show();
});

onChangeSubview: function() {
    this.subview.unbind();
    this.subview.remove();
}

这个 SO question abort-ajax-requests-using-jquery 说您可以将指针存储到 deferred 并通过调用 abort() 来停止它,如下所示:

var fetchXhr = this.model.fetch().done(function() {
  $('#success').show();
});
onChangeSubview: function() {
    fetchXhr.abort();
}

我对每个子视图有几个提取,并且一些在一个间隔内重复,这意味着我必须存储每个提取请求并循环遍历它们,在每个子视图上调用 abort。

有没有更好的方法来阻止延迟函数的执行? 例如:某种检查以查看子视图是否已被删除,或者取消绑定所有延迟承诺的功能?

【问题讨论】:

  • 只是大声思考,您能否将子视图的所有提取添加到列表中,然后 onChangeSubview 您可以遍历它们并执行中止,例如this.fetches.forEach(function(fetchXhr) { fetchXhr.abort(); });(或者_.invoke(this.fetches, 'abort');,如果你想用下划线的方式)。您甚至可以将此功能放在您扩展的基本视图中,以便将其中的一些抽象出来。
  • @Dymos +1。您太谦虚了,这不是评论,而是实际答案;)
  • 哈哈谢谢 :-) 我会把它添加为后代的答案。

标签: javascript jquery backbone.js promise deferred


【解决方案1】:

中止不一定是可取的,因为您可能希望即使隐藏视图也能继续刷新(确认您当前取消绑定/删除)。

您当然可以通过采用一种导致“#success”元素有条件地显示的模式来避免中止的需要,例如通过使用返回显示#success元素的函数的方法来装配$('#success')对象仅当特定子视图(或其容器)可见(或任何适合的标准)时。

// in some suitable outer context
var $success = $('#success');
$success.showConditional = function($container) {
    var $self = $(this);
    return function() {
        if($container.is(':visible')) {
            $self.show();
        }
    }
};

...

$subviewContainer = $("someSelector"); //or maybe the container is already a property of this or this.model?
this.model.fetch().done($success.showConditional($subviewContainer));

在所有提取都采用该模式后,#success 元素将不会显示隐藏或删除的子视图。

这就是原则。您可能需要调整细节以适应您的整体模式。

【讨论】:

  • 正在考虑同样的事情,但不确定如何测试已删除的对象。你的想法是检查视图的缓存 jquery 元素的 DOM 回答了这个问题,但我担心它会在计算上很昂贵,所以我做了以下操作:父视图当前调用 this.subviews.cleanup();删除子视图时。我在子视图的清理函数中添加并设置了一个“已删除”字段:cleanup: function() { this.removed = true; this.remove(); this.unbind();在 ajax 调用中,我进行了检查: this.model.fetch().always(if(!!self.removed){return;} -code-);
  • 看起来很酷。您可以通过从.remove() 返回true 来使.cleanup() 在语法上更简洁,允许您编写this.removed = this.remove()。实际上,如果 this.remove() 有时可能会失败(即不删除),那将很有用,在这种情况下(可能在 try/catch 的帮助下)它可以返回 false
【解决方案2】:

解决此问题的一种方法是将子视图的所有提取添加到列表中,然后onChangeSubview 遍历它们并执行中止,例如

this.fetches.forEach(function(fetchXhr) { 
    fetchXhr.abort(); 
}); 

或者如果你想用下划线的方式来做

_.invoke(this.fetches, 'abort');

您甚至可以将此功能放在您扩展的基本视图中,以便将其中的一些抽象出来。

【讨论】:

  • 这是 OP 正在寻求的“更好的方式”,还是他已经知道的方式?
  • 这是一种不同的方式 :) - 它带来的价值在旁观者的眼中
猜你喜欢
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
  • 2014-03-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
  • 2013-11-11
相关资源
最近更新 更多