How to limit rest calls angular

杀马特。学长 韩版系。学妹 提交于 2019-12-11 17:41:36

问题


I am working on a kanban style drag&drop system with ng2-dragula. And I have an issue, and I think it's because every time you drop an item to a new place it sends the data to the server and redo the whole list of items that you can drag around. And if you do it fast enough you can break the drag&drop cycle. Is there a way to limit the intervall you can make an API call? Similar to RxJS debounceTime, but since the list is almost always changing I cannot pipe a filter to it.

Basic constructor and drag event subscribtion:

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
      }));
  }

First it was for making non draggable items, not it's a bit more:

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');
          }
        });
    }
  }

Dragged item emitting function:

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

Rest call function:

   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(); });
        }
      }

Emitted data cacher:

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

回答1:


Here's one possible implementation:

  • turn drag into an EventEmitter, maintaining your modifyStage method
  • create a destroy$ Subject which emits in ngOnDestroy

Then in 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();

While this is not totally complete, I think it illustrates my approach. What do you think?




回答2:


Since the whole process uses more than one component I managed to get this done in one. With the help of @Will Alexander and this post:debouncing EventEmitter

Final solution is:

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

Added this into constructor

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

And unsubscribe in ngOnDestroy

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


来源:https://stackoverflow.com/questions/57395007/how-to-limit-rest-calls-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!