Как удалить все связанные записи в угловых из нескольких модулей - PullRequest
0 голосов
/ 07 октября 2019

У меня есть несколько модулей в моем угловом приложении, и каждый хранит некоторые связанные данные в моих основных данных. Теперь я хочу удалить свои основные данные, а также удалить все связанные данные.

Итак, я подумал о том, чтобы иметь службу (service1) с методом удаления и заметную, чтобы другие службы знали об этом. данные будут удалены, и другие зависимые службы (service2, service3, ...) подпишутся и удалят связанные с ними данные

@Injectable({
  providedIn: "root"
})
export class Service1Service {
  deleteData$: Subject<string> = new Subject<string>();
  constructor() {
    console.log("Service1Service.constructor");
  }

  delete(id: string) {
    console.log("service1.delete");
    this.deleteData$.next(id);
  }
}
@Injectable({
  providedIn: "root"
})
export class Service2Service {
  constructor(private service1: Service1Service) {
    console.log("Service2Service.constructor");
    this.service1.deleteData$.subscribe(id => this.delete(id));
  }

  delete(id: string) {
    console.log("service2.delete");
  }
}

export class MyComponent {
  constructor(
    private service1: Service1Service,
    ) {}

  delete() {
    this.service1.delete("5");
  }
}

Таким образом, Service2 будет зависеть от Service1, и он будет Открыт / Закрыт, если в будущем будет разработан новый moudle для хранения некоторых других связанных данных в основных данных.

Проблема заключается в том, что если я не добавлю Service2 в компоненты, которыеуже загружены, angular не создает их, поэтому они не подписываются на сервис для удаления данных.

Я пытался использовать providedIn: "root" или напрямую добавлять их в app.module providers без разницы.

Примечание. Я не хочу, чтобы Service1 зависело от других служб, т.е. я не хочу, чтобы service1 вызывал другие службы. Метод удаления

Satckblitz

1 Ответ

1 голос
/ 08 октября 2019

Angular не будет создавать сервис, пока он не потребуется в первый раз по причинам оптимизации. Также, если ваш сервис не используется где-либо в коде, Tree-shaking удалит его из производственного кода. Для получения более подробной информации ознакомьтесь с документацией о провайдерах с возможностью ветвления дерева .

. Я думаю, что в этом случае лучшим решением было бы определение общего интерфейса для всех служб и использование нескольких провайдеров. Это означает, что вы предоставляете несколько услуг для одного и того же интерфейса. Затем вы можете внедрить все сервисы сразу в компонент и выполнить цикл через них и вызвать delete для всех или добавить другой промежуточный сервис, чтобы сделать это, если вам не нужна логика в компоненте. Затем, когда вы добавляете новую услугу, вы просто предоставляете ее в качестве другого поставщика, и все будет работать автоматически. Таким образом, сервисы полностью независимы, а компонент или родительский сервис общаются только с абстрактным интерфейсом.

Вот пример кода для такого решения.

export abstract class ServiceBase {
  public abstract delete(id: string): void;
}

@Injectable()
export class Service1Service extends ServiceBase {
  constructor() {
    super();
    console.log("Service1Service.constructor");
  }

  delete(id: string) {
    console.log("service1.delete");
  }
}

@Injectable()
export class Service2Service extends ServiceBase {
  constructor() {
    super()
    console.log("Service2Service.constructor");
  }

  delete(id: string) {
    console.log("service2.delete");
  }
}

export class AppComponent {
  constructor(
    @Inject(ServiceBase)private services: ServiceBase[],
    ) {}

  delete() {
    this.services.forEach((service) => service.delete());
  }
}

Затем вы регистрируете сервисы. как несколько провайдеров в модуле приложения.

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ],
  providers: [
    { provide: ServiceBase, useClass: Service1Service, multi: true },
    { provide: ServiceBase, useClass: Service2Service, multi: true }
  ]
})
export class AppModule { }

Вот ссылка на форк вашего StackBlitz , который реализует это решение.

Существует также обходной путь дляваше решение для работы, которое не так чисто, поэтому я не рекомендую использовать это. Для этого нужно принудительно создать дочерние службы. Один из способов, который я нашел, - это предоставить пользовательскому инициализатору приложения зависимость от Service2Service, которая вызовет создание. Вот ссылка на сообщение , предлагающее это решение.

Вот пример для вашего случая:

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ],
  providers: [{
    provide: APP_INITIALIZER,
    useFactory: () => () => {},
    deps: [Service2Service],
    multi: true
  }]
})
export class AppModule { }

Ссылка на форкваш StackBlitz , который реализует этот обходной путь.

...