Angular订阅响应重复触发问题求助:弹窗服务调用后响应次数递增
问题分析与解决方案
问题根源
你遇到的重复响应问题,核心原因是PopupDialogService中使用了全局唯一的Subject实例。每次调用confirmationPopup方法时,返回的都是同一个Subject的Observable;而组件每次点击按钮都会新增一个订阅,这些订阅不会自动取消。后续每次调用mySubject.next(true)时,所有已存在的订阅都会收到通知,导致响应次数随点击次数递增。
修复方案
方案1:每次调用创建独立的Subject(推荐)
修改popupDialog.service.ts,为每个弹窗请求创建独立的Subject,确保数据流隔离,同时处理取消逻辑并完成Subject避免内存泄漏:
import { Injectable } from "@angular/core"; import { Observable, Subject } from "rxjs"; import Swal from 'sweetalert2' @Injectable() export class PopupDialogService { confirmationPopup(textDetail?: string): Observable<boolean> { // 为每个弹窗创建独立的Subject const dialogSubject = new Subject<boolean>(); Swal.fire({ title: 'Are you sure?', text: textDetail, icon: 'success', showConfirmButton: true, showCancelButton: true, }).then((result) => { // SweetAlert2中确认状态用isConfirmed判断,而非value dialogSubject.next(result.isConfirmed); dialogSubject.complete(); // 完成流,自动清理订阅 }).catch(() => { dialogSubject.next(false); dialogSubject.complete(); }); return dialogSubject.asObservable(); } }
方案2:直接利用SweetAlert2的Promise转Observable
SweetAlert2的fire()方法本身返回Promise,可直接将其转为Observable,代码更简洁:
import { Injectable } from "@angular/core"; import { from, Observable } from "rxjs"; import Swal from 'sweetalert2' @Injectable() export class PopupDialogService { confirmationPopup(textDetail?: string): Observable<boolean> { const swalPromise = Swal.fire({ title: 'Are you sure?', text: textDetail, icon: 'success', showConfirmButton: true, showCancelButton: true, }).then(result => result.isConfirmed); // 将Promise转为Observable return from(swalPromise); } }
组件优化(可选但推荐)
在组件订阅时添加take(1)操作符,确保只接收一次结果后自动取消订阅,进一步避免潜在的内存泄漏:
import { take } from 'rxjs/operators'; // ... confirmFeatureProductDialog(product){ const message = "Do you want to set this product?"; this._popupDialogService.confirmationPopup(message) .pipe(take(1)) // 仅接收一次数据流,自动取消订阅 .subscribe((res) => { console.log("Running"); if(res){ this.featureProduct(product._id); } }); }
内容的提问来源于stack exchange,提问作者String Name
相关产品推荐
相关产品推荐

