Angular class 使用服务创建循环依赖
Angular class that uses service creates circular dependency
我有一个菜单服务,它使用菜单 classes 保存菜单结构。菜单 classes 使用 menuItem classes.
该服务执行一些 http 请求以获取数据。从这个数据菜单中创建 classes。下面的代码被大大简化了。
import { Injectable, OnInit } from '@angular/core';
import { RequestOptions } from '@angular/http';
import { HttpClient, HttpClientModule, HttpHeaders } from '@angular/common/http';
import { Observable } from "rxjs/Observable"
import { Menu } from "../classes/menu";
import { MenuItem } from "../classes/menuItem";
import { menusResponseInterface } from "../interfaces/menusResponse";
import { DataService } from './data.service';
import { ConfigService } from './config.service';
@Injectable()
export class MenusService {
private menus;
private getMenuesObservers$;
private getMenuesObserver;
private getMenusStateObservers$;
private getMenusStateObserver;
private urls;
constructor(
private http: HttpClient,
private data: DataService,
private config: ConfigService
) {
this.getMenuesObservers$ = [];
this.menus = [];
this.urls = {};
this.init();
}
init(){
this.getMenuesObserver = new Observable(observer => {
this.getMenuesObservers$.push(observer);
});
this.getMenusStateObserver = new Observable(observer => {
this.getMenusStateObservers$ = observer;
});
this.http.get(`${this.config.baseURL}/api/getMenues`).subscribe((response:menusResponseInterface) => {
var index;
for( index in response.menus){
this.menus[index] = new Menu(response.menus[index]);
this.menus[index].setMenuItems(response.pages[index]);
}
for( var i = 0; i< this.getMenuesObservers$.length; i++){
this.getMenuesObservers$[i].next(this.menus);
}
});
}
public getMenues(){
return this.getMenuesObserver;
}
public function getMenuItemByUrl:MenuItem(url:string){
}
}
菜单 Class 创建菜单项的树结构。
import { MenuItem } from "./menuItem";
export class Menu {
public setMenuItems(menuItems){
// loop data and create treeStructure of MenuItems
menuItem = new MenuItem(menuItems);
.
.
.
menuItem.children.push(childMenuItem);
}
}
MenuItem class 包含有关 parent、孩子、姓名和 url 的数据。 url 是通过询问所有 parent 的名字加上自己的名字来创建的。我想再次将 MenuService 注入 MenuItem class,这样我就可以将所有 url 发送给它。我想在 MenuService 中包含所有 URL,以便我可以将它与路由器匹配 url,
import { MenusService } from '../services/menus.service';
import {ReflectiveInjector} from '@angular/core';
export class MenuItem {
public id:number;
public name:string;
private url:string;
.
.
.
public children:Array<MenuItem>;
public parent:MenuItem;
private menuService:MenusService
constructor(
data
){
let injector = ReflectiveInjector.resolveAndCreate([MenusService]);
this.menuService = injector.get(MenusService);
}
.
.
.
public getUrl(){
if(typeof(this.url) == "undefined"){
if(typeof(this.parent) == "undefined" || this.parent.id == 0){
this.url = encodeURI(this.name.replace(new RegExp(/ / , 'g'), '-'));
}
else{
this.url = this.parent.getUrl()+'/'+encodeURI(this.name.replace(new RegExp(/ / , 'g'), '-'));
}
this.menuService.registerURL(this.url, this);
}
return this.url;
}
}
如果不产生循环依赖,这会很好用。
MenuService 使用 Menu,Menu 使用 MenuItem,MenuItem 使用 MenuService。将 MenuService 注入 MenuItem 后 Class 我收到循环依赖警告并且应用程序中断。
有没有 Angular 的方法来解决这个问题而没有这个循环依赖问题?
这里有一些详细说明了我关于使用 Subject 与服务通信的评论:
// MenuItem.ts
static registerUrl:Subject<MenuItem> = new Subject();
// instead of service.registerUrl():
MenuItem.registerUrl.next(this)
// service onInit
MenuItem.registerUrl.subscribe(item => {
// do stuff with item.url
});
瞧,MenuItem 不需要导入服务。
我有一个菜单服务,它使用菜单 classes 保存菜单结构。菜单 classes 使用 menuItem classes.
该服务执行一些 http 请求以获取数据。从这个数据菜单中创建 classes。下面的代码被大大简化了。
import { Injectable, OnInit } from '@angular/core';
import { RequestOptions } from '@angular/http';
import { HttpClient, HttpClientModule, HttpHeaders } from '@angular/common/http';
import { Observable } from "rxjs/Observable"
import { Menu } from "../classes/menu";
import { MenuItem } from "../classes/menuItem";
import { menusResponseInterface } from "../interfaces/menusResponse";
import { DataService } from './data.service';
import { ConfigService } from './config.service';
@Injectable()
export class MenusService {
private menus;
private getMenuesObservers$;
private getMenuesObserver;
private getMenusStateObservers$;
private getMenusStateObserver;
private urls;
constructor(
private http: HttpClient,
private data: DataService,
private config: ConfigService
) {
this.getMenuesObservers$ = [];
this.menus = [];
this.urls = {};
this.init();
}
init(){
this.getMenuesObserver = new Observable(observer => {
this.getMenuesObservers$.push(observer);
});
this.getMenusStateObserver = new Observable(observer => {
this.getMenusStateObservers$ = observer;
});
this.http.get(`${this.config.baseURL}/api/getMenues`).subscribe((response:menusResponseInterface) => {
var index;
for( index in response.menus){
this.menus[index] = new Menu(response.menus[index]);
this.menus[index].setMenuItems(response.pages[index]);
}
for( var i = 0; i< this.getMenuesObservers$.length; i++){
this.getMenuesObservers$[i].next(this.menus);
}
});
}
public getMenues(){
return this.getMenuesObserver;
}
public function getMenuItemByUrl:MenuItem(url:string){
}
}
菜单 Class 创建菜单项的树结构。
import { MenuItem } from "./menuItem";
export class Menu {
public setMenuItems(menuItems){
// loop data and create treeStructure of MenuItems
menuItem = new MenuItem(menuItems);
.
.
.
menuItem.children.push(childMenuItem);
}
}
MenuItem class 包含有关 parent、孩子、姓名和 url 的数据。 url 是通过询问所有 parent 的名字加上自己的名字来创建的。我想再次将 MenuService 注入 MenuItem class,这样我就可以将所有 url 发送给它。我想在 MenuService 中包含所有 URL,以便我可以将它与路由器匹配 url,
import { MenusService } from '../services/menus.service';
import {ReflectiveInjector} from '@angular/core';
export class MenuItem {
public id:number;
public name:string;
private url:string;
.
.
.
public children:Array<MenuItem>;
public parent:MenuItem;
private menuService:MenusService
constructor(
data
){
let injector = ReflectiveInjector.resolveAndCreate([MenusService]);
this.menuService = injector.get(MenusService);
}
.
.
.
public getUrl(){
if(typeof(this.url) == "undefined"){
if(typeof(this.parent) == "undefined" || this.parent.id == 0){
this.url = encodeURI(this.name.replace(new RegExp(/ / , 'g'), '-'));
}
else{
this.url = this.parent.getUrl()+'/'+encodeURI(this.name.replace(new RegExp(/ / , 'g'), '-'));
}
this.menuService.registerURL(this.url, this);
}
return this.url;
}
}
如果不产生循环依赖,这会很好用。 MenuService 使用 Menu,Menu 使用 MenuItem,MenuItem 使用 MenuService。将 MenuService 注入 MenuItem 后 Class 我收到循环依赖警告并且应用程序中断。
有没有 Angular 的方法来解决这个问题而没有这个循环依赖问题?
这里有一些详细说明了我关于使用 Subject 与服务通信的评论:
// MenuItem.ts
static registerUrl:Subject<MenuItem> = new Subject();
// instead of service.registerUrl():
MenuItem.registerUrl.next(this)
// service onInit
MenuItem.registerUrl.subscribe(item => {
// do stuff with item.url
});
瞧,MenuItem 不需要导入服务。