角圆依赖性解决方案

时间:2018-11-28 05:41:25

标签: javascript angular circular-dependency

  • 我有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,还是我自己的自定义弹出式菜单,其中包含主题和所有内容。

2 个答案:

答案 0 :(得分:2)

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

为您服务

cursor.execute("select score*100 from daily_stats1 where  user_id=102")
            rows = cursor.fetchall()
            # Convert query to objects of key-value pairs
            presentmonth1 = list()
            i = 0
            for row in rows[:28]:
                presentmonth1.append(row[i])

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

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

然后在组件中订阅可观察的消息$,然后弹出窗口。

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

确保在ngDestroy上保留或取消保留。

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

答案 1 :(得分:2)

您可以做的是从BIT中删除弹出窗口创建逻辑。这是给您的一些重构。

使用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是因为以后的订户不需要知道前面是否有Subjectalert事件。如果您想拥有这样的逻辑,可以将yesno更改为Subject

创建一个名为BehaviorSubject的组件,并在PopupManager中使用它

app.component

app.component.ts
@Component({
    selector: 'app-root',
    template: `
        <!-- some template -->
        <app-popup-manager></app-popup-manager>
    `
})
export class AppComponent {}

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

为什么不应该将@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... }); } } 暴露给外界?

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