1

我有一个 Angular 应用程序,它具有每个功能模块的架构。我有一个OrdersModule类似的组件ListOfOrdersDetailOfOrder或者EditOfOrder

所有这些组件都需要OrdersApiService在构造函数中,它基本上是一个简单的服务,它使用 REST API 后端通过 HTTPS 提供 CRUD 操作。

OrdersModule与一个名为Order的实体一起工作

我收到了一个功能请求,我将在其中实施新实体,称为Draft Order实际上, Draft OrderOrder之间没有区别(它们包含完全相同的属性,它们以相同的方式创建)但它们必须以不同的方式存储,它们具有不同的 API 端点(myApi.com/ordersvs myApi.com/draft-orders

最简单的方法(从花费时间的角度来看)是将订单复制/粘贴到新模块。但是,我很想避免代码重复,所以这种方法应该对我有用:

{
    path: 'orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule)
},

{
    path: 'draft-orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule)
},

现在我需要根据路由向组件注入不同的服务。我知道解决方法

{
    path: 'orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule),
    data: {
      type: 'orders'
    }
},

{
    path: 'draft-orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule),
    data: {
      type: 'draft-orders'
    }
},

并在服务中使用ActivatedRoute:

constructor(
    private route: ActivatedRoute,
  ) {
    this.type = this.route.snapshot.data['type'];
  }

   getOrders() {
     return this.http.get('myApi.com/' + this.type);
   }

有没有解决方案如何注入整个服务?

谢谢!

4

1 回答 1

0

第一个解决方案

如果你想走硬路线,你可以使用useFactory 方法解决问题。

实现 api 服务并将 api 端点存储到服务的只读字段中。使用useFactory方法注入所有需要的服务以及baseUrl道具。

@Injectable()
export class ApiService {
  constructor(
    private logger: LoggerService,
    private userService: UserService,
    private readonly baseUrl: string
  ) {}

  getUrl() {
    return this.baseUrl;
  }
}

之后,您将需要创建提供程序工厂,您将在其中根据一些信息决定使用哪个 url(我在这个中使用了当前路由)

@NgModule({
  imports: [RouterModule.forChild([{ path: "", component: OrderComponent }])],
  providers: [
    {
      provide: ApiService,
      // List of needed dependecies
      deps: [LoggerService, UserService, Router],
      // Dependencies order should be preserved
      useFactory: (
        logger: LoggerService,
        userService: UserService,
        router: Router
      ) => {
        const isDraft = router.url.includes("draft");

        return new ApiService(
          logger,
          userService,
          isDraft ? OrdersUrl.DRAFT : OrdersUrl.COMMON // inject ORDERS_URL
        );
      }
    }
  ],
  declarations: [OrderComponent]
})
export class OrderModule {}

这样,您将根本没有重复的代码。

Codesandox

第二种解决方案

更简单的方法是决定在 api 服务中正确使用哪个 url。例如,基于当前路线。

于 2020-11-16T21:54:37.227 回答