如何制作调用不同服务的通用方法

Posted

技术标签:

【中文标题】如何制作调用不同服务的通用方法【英文标题】:How to make a generic method that calls different services 【发布时间】:2020-09-25 01:55:44 【问题描述】:

我正在使用 Angular 并且有这个方法:

  loadPagedRecords() 
    this.loadingSpinner = true;
    this.subPage = this.administratorService.getPage(AppSettings.RECORDS_PER_PAGE)
      .subscribe(resp => 
        this.page.recordsList = resp.content;
        this.page.totalElements = resp.totalElements;

        this.pager = this.pagerService.getPager(this.page.totalElements, 1, AppSettings.RECORDS_PER_PAGE);
        this.pagedItems = this.page.recordsList.slice(this.pager.startIndex, this.pager.endIndex + 1);

        this.loadingSpinner = false;
      , (error) => 
        this.loadingSpinner = false;
      );
  

该方法负责在Listing Component中加载Administrators的所有记录。问题是我有其他列出组件(客户端、服务、付款),我在所有这些组件中重复相同的方法(不同之处在于将调用的服务)。

我想做的是用这个方法创建一个抽象类,但它订阅的变量需要是通用的。在上面的示例中,它订阅了 administratorService

我怎样才能使其通用以适用于我的所有列表组件?

编辑:

我做了一些更改,现在该方法按我想要的方式工作了......但不确定这是否是一个好的解决方案:

export abstract class BaseList 

       constructor(protected service: any, protected pagerService: any) 

  loadPagedRecords() 
    this.loadingSpinner = true;
    this.subPage = this.service.getPage(AppSettings.RECORDS_PER_PAGE)
      .subscribe(resp => 
        this.page.recordsList = resp.content;
        this.page.totalElements = resp.totalElements;

        this.pager = this.pagerService.getPager(this.page.totalElements, 1, AppSettings.RECORDS_PER_PAGE);
        this.pagedItems = this.page.recordsList.slice(this.pager.startIndex, this.pager.endIndex + 1);

        this.loadingSpinner = false;
      , (error) => 
        this.loadingSpinner = false;
      );
  


export class ListAdministratorsComponent extends BaseList implements OnInit 

  constructor(private titleService: Title, private router: Router,
    protected administratorsService: AdministratorsService,
    protected pagerService: PagerService,
    private toastrService: ToastrService
  )  
       super(administradoresService, pagerService); 
    

  ngOnInit() 
       this.loadPagedRecords();
  

你怎么看?

【问题讨论】:

你的意思是说每个功能的数据模型都会改变 @Aravind 只是这一行发生了变化: this.administratorService.getPage() 。我需要根据 Component 来设置我在构造函数中注入的 service var。例如,如果用户正在访问 ListAdministrator,则需要使用 administratorService,但如果他正在访问 ListClients,则需要使用 clientsService 来获取正确的数据。 请看我的stackblitz。这是一个如何创建抽象服务并从不同位置覆盖它的示例。另外我强烈建议您阅读services 和他们的scopes 【参考方案1】:

不知道你的应用程序的确切结构,所以我不能说是否有更好的方法,但你可以考虑使用抽象类:

export abstract class RecordViewer<T> 
  abstract readonly serviceGetter = (...args?: any[]) => Observable<T>;

  loadPagedRecords() 
    this.loadingSpinner = true;
    this.subPage = this.serviceGetter(AppSettings.RECORDS_PER_PAGE).pipe(
      finalize(() => this.loadingSpinner = false)
    ).subscribe(resp => 
      this.page.recordsList = resp.content;
      this.page.totalElements = resp.totalElements;
      this.pager = this.pagerService.getPager(
        this.page.totalElements, 1, AppSettings.RECORDS_PER_PAGE
      );
      this.pagedItems = this.page.recordsList.slice(
        this.pager.startIndex, this.pager.endIndex + 1
      );
    );
  

然后你可以从你的组件中扩展它:

export class AdministratorComponent extends RecordViewer<Administrator> 
  readonly serviceGetter = this.administratorService.getPage;

  constructor(private administratorService: AdministratorService) 

【讨论】:

谢谢...我要试试...我在帖子中进行了编辑,请问您是否可以接受? @Andre 您的编辑是否仍会调用相同的服务?可能我没看懂问题 糟糕,我再次编辑了它,抱歉。正如您现在所看到的,抽象类的构造函数具有类型为 any 的变量 service。所以现在我可以将它与每个列表组件一起使用。例如,在 ListClientsComponents 我将使用 super(clientsService, pagerService);并且该方法将从 ClientsService 订阅 getPage().... 你怎么看? @Andre 看起来不错,但您还应该让您的服务扩展某种类或接口来承载 getPage 方法。这样你就不会在你的基类中使用any

以上是关于如何制作调用不同服务的通用方法的主要内容,如果未能解决你的问题,请参考以下文章

通用方法的同步调用 Web API 服务

Alamofire Promise 制作通用请求方法

通用对象向量/数组,其中每个存储的对象都有不同的类

Python接入不同类型数据库的通用接口方法

制作一个适合所有类的通用方法......这可能吗?

如何使用 fetch 制作通用 API 调用函数