繁体   English   中英

角圆依赖性解决方案

[英]Angular Circular Dependency Solution

  • 我有popupservice可以为我打开弹出组件,如下所示:

     export class PopupService { alert() { this.matdialog.open(PopupAlertComponent); } yesno() { this.matdialog.open(PopupYesNoComponent); } custom() { this.matdialog.open(PopupCustomComponent); } } 
  • 然后,我使用this.popupservice.custom()打开自定义弹出窗口。

     export class HomeComponent { constructor(private popupservice: PopupService) {} openCustomPopup() { this.popupservice.custom(); } } 
  • 然后,在我的custom弹出窗口组件中,我想调用自己的alert弹出窗口(报告错误或其他内容):

     export class CustomPopup { constructor(private popupservice: PopupService) {} doHttpCall() { ...do http calls... if (callFailed) this.popupservice.alert('Call Failed'); } } 

我该如何解决循环依赖问题?

笔记:

  • 我已经阅读了其他问题,但我认为我的问题是一个特定的“帮助我”问题。 虽然仍然欢迎您转介我其他问题。
  • this.popupservice.alert()不仅是一个JavaScript alert ,它还是我自己的自定义弹出窗口,具有主题和所有内容。

您的服务不应了解组件,如果您的服务具有组件知识,那将是不好的设计。 您应该在服务中拥有一个类似于行为主题的可观察对象,并使您的组件订阅该可观察对象,以知道何时弹出新消息。

为您服务

message$ = new BehaviourSubject<string>(null);

以及向管道发送消息的功能。

nextMessage(message: string) {
  this.message$.next(message);
}

然后在您的组件中订阅$ observable消息,然后弹出。

this.messageSubscription = this.service.message$.subscribe(message => { this.popup(message); });

确保对ngDestroy进行until或unscbscribe。

ngOnDestroy() {
  if (this.messageSubscription ) {
    this.messageSubscription.unsubscribe();
  }
}

您可以做的是从PopupService弹出创建逻辑。 这是给您的一些重构。

使用PopupService只能从应用程序的不同部分创建事件。

@Injectable()
export class PopupService {
    private _alert: Subject<any> = new Subject();
    private _yesno: Subject<any> = new Subject();
    private _custom: Subject<any> = new Subject();

    // since you didn't like the on- methods, you can do following
    public readonly alert$ = this._alert.asObservable();
    public readonly yesno$ = this._yesno.asObservable();
    public readonly custom$ = this._custom.asObservable();

    onAlert() { return this._alert.asObservable(); }

    onYesno() { return this._yesno.asObservable(); }

    onCustom() { return this._custom.asObservable(); }

    alert(payload) { this._alert.next(payload); }
    yesno(payload) { this._yesno.next(payload); }
    custom(payload) { this._custom.next(payload); }
}

因此,我们有一个PopupService ,它只发出带有一些payload的事件。 我在这里使用Subject是因为以后的订户不需要知道之前是否有alertyesno事件。 如果您想拥有这样的逻辑,则可以将Subject更改为BehaviorSubject

创建一个名为PopupManager的组件,并在app.component使用它

app.component.ts

@Component({
    selector: 'app-root',
    template: `
        <!-- some template -->
        <app-popup-manager></app-popup-manager>
    `
})
export class AppComponent {}
@Component({
   selector: 'app-popup-manager',
   template: '' // don't need to have template
})
export class PopupManagerComponent implements OnInit {
   constructor(private matDialog: MatDialog, private popupService: PopupService) {}

   ngOnInit() {
       this.popupService.onAlert().subscribe(payload => {
       //   this.matDialog.open...
       });

       this.popupService.onYesno().subscribe(payload => {
       //   this.matDialog.open...
       });

       this.popupService.onCustom().subscribe(payload => {
       //   this.matDialog.open...
       });
   }
}

通过这种方式,您可以在所需的任何组件中使用PopupService,因为它现在是单例的独立服务。

为什么不应该将Subject暴露给外界?

您可以想到这种封装类字段。 您确实可以将_alert暴露给外界,但是您将无法控制谁以何种方式使用此主题。 在保持对字段的某些控制的同时,方法总是提供功能的好方法。 将来,您可能想更改服务的内部,也许是某些主题。 如果让应用程序的其他部分直接在字段上访问,则必须进行大量重构。 但是这样,由于您为他们提供了一些方法,所以只要您不破坏这些方法,就可以了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM