Angular 乐观锁定:保存一个数据的多个请求

Angular 乐观锁定:保存一个数据的多个请求,angular,database,optimistic-locking,Angular,Database,Optimistic Locking,正如你在这个例子中看到的。当输入文本的焦点丢失时,它应该导致http请求保存当前数据。当点击复选框时,它也应该保存数据。在这种情况下,它存在以下问题: 焦点丢失在复选框上 编辑名称时,只需单击复选框。它将导致两个事件:焦点丢失和单击。 焦点丢失首先发生,它将调用onBlur()函数,然后单击事件将发生,并调用handleClick()函数 但是在onBlur()函数中,它有http请求。所以应该是这样的:clint没有得到http响应,但是handleClick()再次向restfulapi

正如你在这个例子中看到的。当输入文本的焦点丢失时,它应该导致http请求保存当前数据。当点击复选框时,它也应该保存数据。在这种情况下,它存在以下问题:

  • 焦点丢失在复选框上
编辑名称时,只需单击复选框。它将导致两个事件:焦点丢失和单击。 焦点丢失首先发生,它将调用
onBlur()
函数,然后单击事件将发生,并调用
handleClick()
函数

但是在
onBlur()
函数中,它有http请求。所以应该是这样的:clint没有得到http响应,但是
handleClick()
再次向restfulapi发送相同数据的另一个http请求。数据库具有乐观锁,这将导致第二个请求失败

而且,如果数据只是一个新对象,它还没有保存到数据库中,那么它的id为null。当焦点丢失时,它应该导致http POST,然后客户端得到http响应,数据得到ID。实际上客户端不会等待得到http响应,只需调用
handleClick()
函数,数据仍然没有ID,它将导致同一数据上的另一个http POST


有没有更好的办法来解决这个问题?请提供帮助。

在这种情况下,您可以将rxjs与
去BounceTime
结合使用:

export class AppComponent implements OnInit  {
  data: MyObject;

  private saveData$ = new Subject<void>();
  private destroy$ = new Subject<void>();

  ngOnInit() {
    // in real situation, data should come from restful api, or just a new objecy.
    this.data = {
        name: 'qqq',
        aa: false,
        bb: true
    };

    this.saveData$.pipe(
      debounceTime(100),
      takeUntil(this.destroy$);
    ).subscribe(() => {
      // http POST or PUT
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  handleClick() {
    this.saveData$.next();
  }

  onBlur() {
    this.saveData$.next();
  }
}
导出类AppComponent实现OnInit{
资料:MyObject;
私有存储数据$=新主题();
private destroy$=新主题();
恩戈尼尼特(){
//在实际情况中,数据应该来自RESTfulAPI,或者只是一个新对象。
此参数。数据={
名称:“qqq”,
aa:错,
是的
};
此.saveData$.pipe(
去BounceTime(100),
takeUntil(这个.destroy$);
).订阅(()=>{
//http POST或PUT
});
}
ngOnDestroy():void{
this.destroy$.next();
此.destroy$.complete();
}
handleClick(){
此.saveData$.next();
}
onBlur(){
此.saveData$.next();
}
}
您可以在代码中使用“提交”标志。这样,您在任何情况下都不会多次提交表格。此外,您还可以使用相同的标志来禁用“提交”按钮。检查我根据您的代码制作的Stackblitz示例:

要点是提交方法:


  submit() {
    if (this.submitting) {
      return;
    }
    this.submitting = true;
    console.log("submitting: ", this.submitting);
    const data = {};
    this.http.post("http://yourapi.com", data).subscribe(res => {
      this.submitting = false;
    },
      err => {
        console.log(err);
        setTimeout(() => {
          this.submitting = false;
        }, 3000);

      }
    )
  }

在这种情况下,更好的方法可能是使用submit按钮对所有表单数据进行一次调用。忘了在示例中提到,当您单击按钮或触发onBlur事件时,您可以看到在这两种情况下如何禁用submit按钮。我尝试过,如果有多个数据,则使用bufferTime可能更好。
export class AppComponent implements OnInit  {
  data: MyObject;

  private saveData$ = new Subject<void>();
  private destroy$ = new Subject<void>();

  ngOnInit() {
    // in real situation, data should come from restful api, or just a new objecy.
    this.data = {
        name: 'qqq',
        aa: false,
        bb: true
    };

    this.saveData$.pipe(
      debounceTime(100),
      takeUntil(this.destroy$);
    ).subscribe(() => {
      // http POST or PUT
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  handleClick() {
    this.saveData$.next();
  }

  onBlur() {
    this.saveData$.next();
  }
}

  submit() {
    if (this.submitting) {
      return;
    }
    this.submitting = true;
    console.log("submitting: ", this.submitting);
    const data = {};
    this.http.post("http://yourapi.com", data).subscribe(res => {
      this.submitting = false;
    },
      err => {
        console.log(err);
        setTimeout(() => {
          this.submitting = false;
        }, 3000);

      }
    )
  }