Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用RxJS正确实现一次点击激活操作按钮?_Javascript_Angular_Typescript_Rxjs_Observable - Fatal编程技术网

Javascript 如何使用RxJS正确实现一次点击激活操作按钮?

Javascript 如何使用RxJS正确实现一次点击激活操作按钮?,javascript,angular,typescript,rxjs,observable,Javascript,Angular,Typescript,Rxjs,Observable,我还在学习RxJS。对于我的一个项目,我想实现这个“只保存一次”功能 关于RxJs的视频中的代码片段如下: const clickToSave$ = saveClick$.pipe( exhaustMap(() => http.post(saveURL, data) ) ) 我有以下重写的代码,其中我尝试将代码片段实现到现有的代码库中 const saveClick$ = new Observable(); // TODO: error handling con

我还在学习RxJS。对于我的一个项目,我想实现这个“只保存一次”功能

关于RxJs的视频中的代码片段如下:

const clickToSave$ = saveClick$.pipe(
    exhaustMap(() => http.post(saveURL, data) )
)
我有以下重写的代码,其中我尝试将代码片段实现到现有的代码库中

 const saveClick$ = new Observable();
    // TODO: error handling
    const clickToSave$ = saveClick$.pipe( exhaustMap(() => this.http.post(this.xmlendpointPdf, jsonType, this.httpOptions) )
      ).subscribe(
        result => {
          const docUrl = 'test';
          console.log(docUrl);        },
        error => {
          if (error['status'] === 0) {
            this.openAlertDialog('Unknown error');
          } else {
          this.openAlertDialog('The following error has appeared:' + error['statusText']);
          }
          console.log('There was an error: ', error);
        });
      }
…但它显然不起作用。我应该如何绑定到按钮HTML中的
(单击)=..
事件?
总而言之,我想要的是,理论上你可以点击按钮,但它会在一段时间内只做一次操作(在本例中是
http.post
call),因此当用户通过点击发送按钮时。我如何才能成功地为我自己的特定用例实现这个代码片段(我想未来很多人也会寻找这个用例)。

如果需要更多解释,请随时提问

模板

<button (click)="bntClicked($event)">Save Button</button>
<br />
<button #btn>Save Button 2</button>
export class AppComponent implements OnInit {
  //Solution 1 - Not a big fan of this one personally but it does work
  //Manually make sure a subscription finishes before allowing a new one
  activeSubscription: Subscription;
  bntClicked($event) {
    if (!this.activeSubscription) {
      this.activeSubscription = this.saveMock().subscribe({
        next: result => {
          console.log(result);
          this.resetSubscription();
        }
      });
    }
  }

  resetSubscription() {
    this.activeSubscription.unsubscribe();
    this.activeSubscription = undefined;
  }
  //End solution 1;

  //Solution 2 - I prefer this one

  //We get a reference to the button using ViewChild
  @ViewChild("btn", { static: true }) button: ElementRef;

  ngOnInit(): void {
    //Option 1
    fromEvent(this.button.nativeElement, "click")
      .pipe(
        //Cancel previous observable and subscribe to new/last one
        switchMap($event => this.saveMock())
      )
      .subscribe({
        next: result => console.log("switchMap", result)
      });

    //Option 2
    fromEvent(this.button.nativeElement, "click")
      .pipe(
        debounceTime(1000),
        mergeMap($event => this.saveMock())
      )
      .subscribe({
        next: result => console.log("debounceTime", result)
      });
  }
  //End solution 2;

  saveMock(): Observable<any> {
    return of({ description: "Hello World!" }).pipe(delay(1000));
  }
}

保存按钮

保存按钮2
代码

<button (click)="bntClicked($event)">Save Button</button>
<br />
<button #btn>Save Button 2</button>
export class AppComponent implements OnInit {
  //Solution 1 - Not a big fan of this one personally but it does work
  //Manually make sure a subscription finishes before allowing a new one
  activeSubscription: Subscription;
  bntClicked($event) {
    if (!this.activeSubscription) {
      this.activeSubscription = this.saveMock().subscribe({
        next: result => {
          console.log(result);
          this.resetSubscription();
        }
      });
    }
  }

  resetSubscription() {
    this.activeSubscription.unsubscribe();
    this.activeSubscription = undefined;
  }
  //End solution 1;

  //Solution 2 - I prefer this one

  //We get a reference to the button using ViewChild
  @ViewChild("btn", { static: true }) button: ElementRef;

  ngOnInit(): void {
    //Option 1
    fromEvent(this.button.nativeElement, "click")
      .pipe(
        //Cancel previous observable and subscribe to new/last one
        switchMap($event => this.saveMock())
      )
      .subscribe({
        next: result => console.log("switchMap", result)
      });

    //Option 2
    fromEvent(this.button.nativeElement, "click")
      .pipe(
        debounceTime(1000),
        mergeMap($event => this.saveMock())
      )
      .subscribe({
        next: result => console.log("debounceTime", result)
      });
  }
  //End solution 2;

  saveMock(): Observable<any> {
    return of({ description: "Hello World!" }).pipe(delay(1000));
  }
}

导出类AppComponent实现OnInit{
//解决方案1-个人不太喜欢这个,但它确实有效
//手动确保订阅在允许新订阅之前完成
activeSubscription:订阅;
bntClicked($event){
如果(!this.activeSubscription){
this.activeSubscription=this.saveMock().subscripte({
下一步:结果=>{
控制台日志(结果);
这是resetSubscription();
}
});
}
}
重置订阅(){
this.activeSubscription.unsubscripte();
this.activeSubscription=未定义;
}
//最终解决方案1;
//解决方案2-我更喜欢这个
//我们使用ViewChild获得对按钮的引用
@ViewChild(“btn”,{static:true})按钮:ElementRef;
ngOnInit():void{
//选择1
fromEvent(this.button.nativeElement,“单击”)
.烟斗(
//取消以前的可观察项并订阅新的/最后一个
switchMap($event=>this.saveMock())
)
.订阅({
下一步:result=>console.log(“开关映射”,result)
});
//选择2
fromEvent(this.button.nativeElement,“单击”)
.烟斗(
去BounceTime(1000),
mergeMap($event=>this.saveMock())
)
.订阅({
下一步:result=>console.log(“debounceTime”,result)
});
}
//最终解决方案2;
saveMock():可观察