【问题标题】:How to limit rest calls angular如何限制休息呼叫角度
【发布时间】:2019-08-07 12:55:17
【问题描述】:

我正在使用 ng2-dragula 开发看板样式的拖放系统。 我有一个问题,我认为这是因为每次您将一个项目放到一个新位置时,它都会将数据发送到服务器并重做您可以拖动的整个项目列表。如果你做得足够快,你可以打破拖放循环。 有没有办法限制您可以进行 API 调用的时间间隔?与 RxJS debounceTime 类似,但由于列表几乎总是在变化,我无法通过管道将过滤器传递给它。

基本构造函数和拖拽事件订阅:

constructor(private dragulaService: DragulaService, ) {
    this.makeUndragabbles(); 
    this.subs.add(this.dragulaService.dropModel('cardList')
      .subscribe(({ item, target, source }) => {
        const dragObj: DragObject = {
          item: item,
          stageId: target['id'],
          name: this.pipelineConfig.name
        };
        this.modifyStage(dragObj);
        const drake = this.dragulaService.find('cardList').drake; //debug variable
        const sourceModel = drake.models[drake.containers.indexOf(source)]; //debug variable
      }));
  }

首先是为了制作不可拖动的项目,而不是更多:

private makeUndragabbles() {
    if (!this.dragulaService.find('cardList')) {
      this.dragulaService.createGroup('cardList',
        {
          copy: false,
          revertOnSpill: true,
          moves: (el, container, handle, sibling) => {
            return !el.classList.contains('nodrag');
          },
          isContainer: (el) => {
            return el.classList.contains('stage');
          }
        });
    }
  }

拖动项发射功能:

private modifyStage(draggedItem) {
    this.drag.emit(draggedItem);
  }

休息调用函数:

   private saveDraggedItem(pipelineType: string, statusChangeDTO: StatusChangeDTO) {
        if (pipelineType === 'dealStages') {
          this.dealService.savePipelineDealStageUsingPOST(statusChangeDTO).pipe(
            debounceTime(1000),
          )
            .subscribe(res => { }
              , (err) => this.error.emit(err)
              , () => { this.getAllDealsForPipeline(); });
        }
      }

发射数据缓存器:

  drag(draggedItem: DragObject) {
    if (draggedItem.item) {
      const statusChange: StatusChangeDTO = {
        id: draggedItem.item.id,
        newStatusId: +draggedItem.stageId
      };
      this.saveDraggedItem(draggedItem.name, statusChange);
    }
  }

【问题讨论】:

  • 你总是可以尝试编写一个拦截器,但这会很脏。这听起来像是 Dragula 的问题。有什么理由不使用 Angular Material CDK?
  • @WillAlexander 是的,我正在做的项目是一个公司项目,一切都是用引导样式完成的。我建议使用那个,但它被拒绝了。但最终可能是这样。我试图解决原始的dragula文件,因为它缺少未定义和/或空检查,并且我将它带到了一个工作阶段,但是当错误发生时它突然复制了该项目。因此,我最终在其中一个列表中重复了相同的项目(如果我将原始项目放在列表中,它就会消失),但这很烦人
  • 另一种选择是编写自己的拖放。它是在重新发明轮子,但它会让你完全按照你想要的方式处理所有事情,而且如果你对 RxJS 很了解,这并不太难……
  • 消费组件使用得很好,所以如果不是必须的,我不会重新发明轮子。也许dragula 不是这类d&d 任务的最佳选择。但我尽力解决我面临的问题。但是,如果我对其余的调用本身进行 debounceTime ,它并没有真正起作用。
  • Dragula 如何订阅您的 HTTP 调用?

标签: angular drag-and-drop rxjs delay delayed-execution


【解决方案1】:

这是一种可能的实现方式:

  • drag 转换为EventEmitter,保持您的modifyStage 方法
  • 创建一个destroy$Subject,它在ngOnDestroy中发射

然后在ngOnInit:

this.drag.pipe(
  takeUntil(this.destroy$),
  debounceTime(1000),
  filter(item => !!item.item)
  map(item => {
    const statusChange: StatusChangeDTO = {
      id: draggedItem.item.id,
      newStatusId: +draggedItem.stageId
    };
    return { name: item.name, status: statusChange }
  }),
  filter(data => data.name === 'dealStages'),
  concatMap(data => this.dealService.savePipelineDealStageUsingPOST(data.status))
  // depending on requirements, perhaps use switchMap or exhaustMap
).subscribe();

虽然这并不完全完整,但我认为它说明了我的方法。你怎么看?

【讨论】:

    【解决方案2】:

    由于整个过程使用了多个组件,因此我设法将其合二为一。 在@Will Alexander 和这篇文章的帮助下:debouncing EventEmitter

    最终解决方案是:

    subs = new Subscription();
    debouncer = new Subject();
    

    添加到构造函数中

    this.subs.add(this.debouncer.pipe(
          debounceTime(500))
          .subscribe((val) => this.drag.emit(val)));
    

    并在 ngOnDestroy 中取消订阅

     ngOnDestroy() {
        this.subs.unsubscribe();
      }
    

    【讨论】:

    • 但它引入了一个新问题。如果我在 debounceTime 内拖动多个项目,则由于该行为,只有最后一个项目会被保存。关于我该如何应对的任何提示?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2016-08-21
    • 2016-06-13
    相关资源
    最近更新 更多