角圆依赖警告 [英] Angular circular dependency warning

查看:73
本文介绍了角圆依赖警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr:向下滚动到解决方案

tl;dr: scroll down to solution

我有一个循环依赖关系,并且正在得到警告,这是正确的,但是,我正在对其进行管理.问题是我有一个聊天组件.在角落,您可以选择查看他们的个人资料页面,而在他们的个人资料页面中,您可以选择向他们发送消息,因此是循环依赖关系.我正在通过

I have a circular dependency and I am getting a warning, rightfully so, however, I am managing it. The issue is that I have a chat component. In the corner you can select to see their profile page, while in their profile page you have the option to send them a message, hence the circular dependency. I am managing this by

public async openProfile(): Promise<void> {
  this.modalCtrl.dismiss(); //closing the chat component before opening the profile modal
  const profile = await this.modalCtrl.create({
    component: ProfileComponent,
  });
  await profile.present();
} 

profile.component

public async openChat(): Promise<void> {
  this.modalCtrl.dismiss(); //closing the profile component before opening the chat modal
  const chat = await this.modalCtrl.create({
    component: ProfileComponent,
  });
  await chat.present();
} 

有没有更简单的方法来处理这种循环依赖?

Is there an easier way of handling this circular dependency?

更新:根据下面的建议,我尝试创建服务.但是,现在我有了一个三向依赖关系圈:

UPDATE: as per the suggestion below I tried creating a service. However now I have a three way dependency circle:

private modalService: ModalService;

constructor(modalService: ModalService){
  this.modalService = modalService
}

public async openProfile(): Promise<void> {
  this.modalService.openProfile(this.userData);
} 

profile.component

private modalService: ModalService;

constructor(modalService: ModalService){
  this.modalService = modalService
}

public async openChat(): Promise<void> {
  this.modalService.openChat(this.userData);
}

modal.service

import { ModalController } from '@ionic/angular';
import { Injectable } from '@angular/core';
import { ProfileComponent } from '../../components/profile/profile.component';
import { ChatComponent } from '../../components/chat/chat.component';
import { UserData } from '../../interfaces/UserData/userData.interface';

@Injectable({
  providedIn: 'root',
})
export class ModalService {
  private modal: ModalController;
  public constructor(modal: ModalController) {
    this.modal = modal;
  }

  public async openProfileComponent(user: UserData): Promise<void> {
    this.modal.dismiss();
    const profile = await this.modal.create({
      component: ProfileComponent,
      componentProps: {
        contact: user,
      },
    });

    await profile.present();
  }

  public async openChatComponent(user: UserData): Promise<void> {
    this.modal.dismiss();
    const chat = await this.modal.create({
      component: ChatComponent,
      componentProps: {
        contact: user,
      },
    });

    await chat.present();
  }

  public close(): void {
    this.modal.dismiss();
  }
}

UPDATE Stackblitz在Ionic 4上过于不稳定,因此我无法在其上进行复制,因此这是要点以及相关信息和相关代码.

UPDATE Stackblitz is too unstable with Ionic 4 so I can't replicate on it so here is a gist with the information and related code.

UPDATE2 我接受了答案中提到的建议,但仍然出现错误.为此,我创建了一个如下所示的 shared.module.ts :

UPDATE2 I took the advice mentioned in answers but still getting the error. In order to do that, I created a shared.module.ts that looks like this:

import { UserService } from './componentServices/user/user.service';
import { ModalService } from './componentServices/modal/modal.service';
import { AuthenticationSecurityService } from './componentServices/auth_security/authentication-security.service';
import { AuthGuardService } from '../_guards/auth-guard.service';
import { ApiService } from './componentServices/api/api.service';
import { ChatService } from './components/chat/socketIO/chat.service';

@NgModule({
  imports: [CommonModule, ReactiveFormsModule, IonicModule.forRoot(), FormsModule, IonicModule],
  declarations: [
    // various components
  ],
  exports: [
    // various components and common modules
  ],
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [
        UserService,
        ModalService,
        DashboardService,
        AuthenticationSecurityService,
        AuthGuardService,
        ApiService,
        ChatService,
      ],
    };
  }
}

app.module.ts

imports: [
    SharedModule.forRoot(),
]

client:135 Circular dependency detected:
src/sharedModules/componentServices/modal/modal.service.ts -> src/sharedModules/components/profile/profile.component.ts -> src/sharedModules/componentServices/modal/modal.service.ts

client:135 Circular dependency detected:
src/sharedModules/components/chat/chat.component.ts -> src/sharedModules/components/search/search.component.ts -> src/sharedModules/components/profile/profile.component.ts -> src/sharedModules/componentServices/modal/modal.service.ts -> src/sharedModules/components/chat/chat.component.ts

client:135 Circular dependency detected:
src/sharedModules/components/profile/profile.component.ts -> src/sharedModules/componentServices/modal/modal.service.ts -> src/sharedModules/components/profile/profile.component.ts

client:135 Circular dependency detected:
src/sharedModules/components/search/search.component.ts -> src/sharedModules/components/profile/profile.component.ts -> src/sharedModules/componentServices/modal/modal.service.ts -> src/sharedModules/components/chat/chat.component.ts -> src/sharedModules/components/search/search.component.ts

解决方案

正如@ bryan60和@Luis所说,必须有一个缓冲区,所以我所做的就是遵循他们俩都建议的发射路线.Bryan给出了更多代码,其中Luis给出了重要的职责摘要.这是我重构的方式:

SOLUTION

as @bryan60 and @Luis said there has to be a buffer, so what I did was follow the emitting route that they both had suggested. Bryan gives more code look like, where Luis gives a great responsibility summary. here is how I refactored it:

  public initializeApp(): void {
    this.platform.ready().then((): void => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this._subToObservables();
    });
  }

  private _subToObservables(): void {
    this.modalService.openModal$.subscribe(
      async (e: ModalEmitInterface): Promise<void> => {
        const { command, data } = e;
        switch (command) {
          case 'open-profile':
            const profile = await this.modalCtrl.create({
              component: ProfileComponent,
              componentProps: {
                contact: data,
              },
            });
            await profile.present();
            break;

          case 'open-chat':
            // same as above
            break;

          default:
            break;
        }
      },
    );
  }

modalSignal.service.ts

export class ModalService {
  private openModalSubject: Subject<ModalEmitInterface> = new Subject<ModalEmitInterface>();
  public readonly openModal$: Observable<ModalEmitInterface> = this.openModalSubject.asObservable();

  private emitPayload: ModalEmitInterface;
  public openProfileComponent(user: UserData): void {
    this.emitPayload = {
      command: 'open-profile',
      data: user,
    };
    this.openModalSubject.next(this.emitPayload);
  }

  // repeat for others
}

chat.component.html

<button (click)="openProfile(user)">click me</button>

chat.component.ts

chat.component.ts

export class ChatComponent {
  public constructor(private modalSignal: ModalService){}

  private openProfile(user: UserData): void {
    this.modalSignal.openProfileComponent(user);
  }
}

就这样,尽管您仍然需要确保要关闭模式,否则它们将继续堆积.

thats it, although you still need to make sure that you are closing the modals or they will continue to stack.

推荐答案

在这种情况下出现了几次.我每次都得到相同的解决方案,并且对我来说扩展性很好,所以就行了.

Been in that situation a couple of times. I end up with the same solution everytime and it scaled very well for me, so here it goes.

您将需要一项服务(由其他人建议),但也需要一个公正的参与者.想法是将服务用作两个相互依赖的组件之间的通信/消息缓冲区,以帮助打破交叉引用.为了举例,我们假设"App.Component".

You will need a service (as suggested by others), but also an, let's call it, impartial player. The idea is to use the service as the communication/messaging buffer between the two interdependent components to help break the cross reference. For the sake of an example, let's assume the "App.Component".

组成和职责:

Modal.Service :接收消息以执行操作.可以通过单个方法接收指示动作的字符串或对象,也可以通过每个动作的多个方法.实施细节由您决定.

Modal.Service: Receives messages to execute actions. It could be through single method receiving a string or object indicating the action or multiple methods for every action. Implementation details is up to you.

App.Component :获取ModalService注入并订阅消息事件.根据动作消息,然后激活相应的模态.

App.Component: Gets the ModalService injected and subscribes to the message event. Based on the action message, then activates the corresponding modal.

聊天组件:获取注入的Modal.Service并发送一条消息,指示要执行的操作,即显示配置文件.

Chat.Component: Gets the Modal.Service injected and sends a message indicating the action to be performed, i.e. show the profile.

Profile.Component :获取注入的Modal.Service并发送一条消息,指示要执行的操作,即发送一条消息.

Profile.Component: Gets the Modal.Service injected and sends a message indicating the action to be performed, i.e. send a message.

这很好地扩展,并且该服务可以用作其他几个模块和/或组件之间的通信缓冲区.

This scales very well and the service can be used as a communication buffer between several other modules and/or components.

这篇关于角圆依赖警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆