【发布时间】:2018-04-02 15:31:34
【问题描述】:
修改问题标题
原来的问题标题是这样的:
Angular 2/4 Observable - 如何修改发出值的对象 在订阅内部而不触发更多事件?
经过不是问题原因的广泛调查,但是这里的 cmets 中有关于如何解决该特定问题的建议。实际问题与同时拥有多个 ng2-dragula 订阅者有关,因此我更新了问题标题以反映这一点。
我正在使用 ng2-dragula 插件并订阅 dropModel 事件。
我面临的问题是在订阅代码中我需要通过重新排列模型中的其他项目来修改模型。这会导致 dropModel 再次触发 dropModel 事件 - 它显然认为是因为我更改了用户执行拖放操作的列表中的模型位置,而不是我的代码。
我尝试了 take(1) 但这并没有解决问题 - 它只是不断地接受一个事件,所以当我在 subscribe 中更改模型时,显然它会再次接受下一个 (1)。
这是代码:
this._dragulaService.dropModel.take(1).subscribe(() => {
// For ease, we just copy all the values into the model and then destroy
// the itemsControl, then patch all model values back to the form
// This is easier than working out which item was dragged and dropped where
// (and on each drop we want to save the model, so we would need to update it anyway)
this.itemsControl['controls'].forEach((formGroup, index) => {
this.template.template_items[index].sort = index; // ensures the API will always return items in the index order
console.log('copying ID', formGroup['controls'].id.value);
this.template.template_items[index].id = formGroup['controls'].id.value;
this.template.template_items[index].item_type = formGroup['controls'].item_type.value;
this.template.template_items[index].content = formGroup['controls'].content.value;
this.template.template_items[index].is_completed = formGroup['controls'].is_completed.value;
});
}
理想情况下,我希望“抓取”第一个 drop 事件(用户发起),然后在订阅代码中,取消订阅或停止接收更多事件,然后处理模型,最后重新订阅。
我知道这有点奇怪 - 在订阅异步代码中,我需要以某种方式“暂停”订阅。尽管“暂停”并不完全正确——我实际上想以某种方式阻止触发新事件,直到我完成对当前事件的处理。暂停只会导致我处理自己的事件(如果有意义的话)。这可能吗?
注意
dragula 在这里绑定的模型是 itemsControls 的动态数组,而不是通常意义上的纯数据模型。因此,我从表单控件中提取数据并插入到实际的数据模型中。
更新 1
我决定记录 Dragula 对我绑定的 itemsControl(AbstractControls 数组)所做的事情。
在拖动之前,我记录了数组中的实际内容:
itemsControl is now this: (4) [FormGroup, FormGroup, FormGroup, FormGroup]
在 dropModel 订阅处理程序中,我记录了一个“dropped”事件和数组的长度。这是我拖放任何项目时的输出,总是相同的输出:
dropped
length is 3
dropped
length is 3
dropped
length is 4
dropped
length is 5
dropped
length is 5
dropped
length is 4
dropped
length is 4
但是,如果我删除我在上面发布的代码(即,我不会触及底层数据模型),这就是输出:
dropped
length is 4
dropped
length is 4
因此,至少这证明了通过重新排序数据,我不仅会引发更多事件(正如我所怀疑的那样),而且还会产生奇怪的副作用,即控件数组的长度正在增加和减少(不知道为什么就是)。
鉴于此输出,我需要一种仅对发出的最后一个事件采取行动的方法。
有没有办法只从 Observable 中获取最后一个事件?
更新 2
根据this,这里真正的问题是ng2-dragula 不支持将dropModel 绑定到FormArray。但似乎有一种解决方法......仍在寻找!
【问题讨论】:
-
用 throttleTime(0) 或 debounceTime(0) 限制 observable 不会修复它,对吗?
-
@estus 我不知道,但我会尝试。
-
@estus 看来 debounceTime(0) 确实可以解决它...您是否能够创建一个答案来解释为什么会这样?
-
@estus 好的,我的错,在我重新加载应用程序并进一步测试后,它没有修复它
-
我无法接受这个例子,但过滤和限制是避免递归事件的常用方法。由于这是一个复杂的问题,我建议提供stackoverflow.com/help/mcve 以重现该问题。您也可以尝试更大的延迟,以防万一这可以作为快速修复,throttleTime(10) 或 debounceTime(10)。
标签: angular rxjs observable ng2-dragula