想要观察者只提供一个真假值

时间:2019-08-16 07:20:08

标签: angular typescript observable

我用过p-toast的一个messagBox。当我单击删除时,我想输入是或否值,然后它将按api键删除该项目。不,它不会做任何事情。这件事正在工作,但是当我单击第一个项目时,我单击否,然后我单击第二个项目,然后在消息框中单击“是”,此后它将删除第一和第二个项目。我首先要删除当前项目。

messagebox.service.ts:

public messageSource = new BehaviorSubject(false);   currentMessage =
 this.messageSource.asObservable();

   public _msgBoxSubject: EventEmitter<boolean> = new
 EventEmitter<boolean>();   public confirmResponse: boolean = false;  
 response: boolean = false;

   show() {
     this.messageSource.next(false);
     this.response = true;
     this._msgBoxSubject.emit(this.response);   }

   onYes(value) {
     this.messageSource.next(value);
     this.confirmResponse = value;   }

   onNo(value1) {
     this.confirmResponse = value1;   }

  hide() {
     this.response = false;
     this._msgBoxSubject.emit(this.response);   }

   getMsgBoxEmitter() {
     return this._msgBoxSubject;   }

messagebox.component.ts:

 ngOnInit() {
     this._msgBoxService.getMsgBoxEmitter().subscribe((value: boolean) => {
       this.messageService.clear();
       this.messageService.add({ key: 'c', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: 'Confirm to proceed' });
     });    }

   onConfirm() {
     this.messageService.clear('c');
     this._msgBoxService.onYes(true);   }

   onReject() {
     this.messageService.clear('c');   }

emailmaster.component.ts: (我在单击删除按钮时调用此功能)

  deleteEmail(ID: Email) {
        this._msgBoxService.show();
        this._msgBoxService.currentMessage.subscribe(response1 => {
           if (response1 === true) {
             this._masterservice.deleteEmail(ID).subscribe(data => {
               this._toasterService.showMessage('Email deleted successfully', 'Success Message', 'success');
               if (data) {
                 this.GetEmails();
               }
             });
           }
        });
       }

我只希望在单击消息框的“是”时删除当前项目。

2 个答案:

答案 0 :(得分:1)

您的deleteEmail方法并未取消订阅currentMessage的Observable。尝试如下操作:

deleteEmail(ID: Email) {
  this._msgBoxService.show();
  this._msgBoxService.currentMessage.pipe(
    filter(response1 => response1), // only allows true values through
    take(1), // takes one emission per subscription and then completes
    mergeMap(() => this._masterservice.deleteEmail(ID)), // mergeMap can be used safely because you're only getting one emission
    tap(() => this._toasterService.showMessage('Email deleted successfully', 'Success Message', 'success')),
    filter(data => !!data), // only emissions where data exists here will continue
    tap(() => this.GetEmails())
  ).subscribe();
}

我还建议您添加错误处理,因为如果此处出现任何故障,您将不会发现它。例如,您可以添加一个catchError块。

答案 1 :(得分:1)

因此,正如另一个答案所建议的那样,我认为问题是,您从未取消对currentMessage的deleteEmail函数中的订阅,因此它是基于先前的尝试

deleteEmail(ID: Email) {
        this._msgBoxService.show();
        this._msgBoxService.currentMessage.subscribe(response1 => {
           if (response1 === true) {
             this._masterservice.deleteEmail(ID).subscribe(data => {
               this._toasterService.showMessage('Email deleted successfully', 'Success Message', 'success');
               if (data) {
                 this.GetEmails();
               }
             });
           }
        });
       }

当前流量示例。

您对deleteEmail的呼叫会弹出一个确认,并且您的代码订阅了答案,并寻找了答案。

您单击否(否),确认消失,但订阅仍在继续收听。

您的下一个删除电子邮件的呼叫弹出一个确认,您的代码再次订阅答案,现在有两个订阅正在侦听。

您单击“是”(true),这两个订阅都将跳入操作,发送对第一项和第二项的删除请求。


另一位发贴人的想法是正确的,但他们的方法行不通,因为只有当事情是真的时,您的服务才会发出。它永远不会说什么时候是假的。因此,尝试take(1)意味着它将就坐在那儿,直到有人说是。

所以我们需要做一些小改动才能使它工作。

第1步使用take(1)

    this._msgBoxService.currentMessage
        .pipe(take(1)) // this completes the observable after hearing 1 value from it
        .subscribe(response1 => {

第2步拒绝时要做的事

   onReject() {
     this.messageService.clear('c');   
     this._msgBoxService.onNo(false); // send the onNo when rejected   

步骤3发出onNo调用时的值

   onNo(value1) {
     this.messageSource.next(value1); // when onNo called, emit the value so old subscribers can complete
     this.confirmResponse = value1;   }

还建议删除节目中虚假值的散发,因为这可能会使事情混淆

   show() {
     // this.messageSource.next(false); // remove this line to avoid hearing it's emit 
     this.response = true;