建立服务的正确方式是什么



开发者周一快乐

我有一个问题要问大家,我自己都没能回答。

我目前正在构建一个应用程序,该应用程序从服务中获取大量数据,这些服务本身会发出一些API请求。

现在,在我的应用程序对用户可用之前,我需要完成所有这些API调用。

现在我的问题是:"构建依赖数据的应用程序结构的正确方法是什么"。

当前实施的解决方案:

每个服务本身都有一些函数,然后创建一些HTTPget请求。

我目前有一个主要服务,它导入所有其他服务。然后,我有一大堆的承诺,一个接一个地控制流量。现在,如果我想在应用程序开始时这样做一次,这就很好了。但我现在也想在运行应用程序的过程中进行同样的调用。但是,每当我从另一个服务导入这个主服务时,我都会创建一个循环依赖,因为主服务会导入所有可用的服务。

现在,正确的处理方法是什么我需要一个可以调用的函数,它可以检索我的应用程序所需的所有数据,并且我应该能够从应用程序中的任何组件和/或服务调用该函数,而不会创建循环依赖关系。

你们会怎么解决这个问题?有最佳实践吗

**仅供参考,这不是一个标准的应用程序,而是一个"信息亭"。我们最初希望获得所有的数据,这样应用程序几乎永远不需要加载。此外,当我调用该函数来重新检索所有数据时。**

主要服务代码示例:

constructor(
private testservice1: TestService1,
private testservice2: TestService2,
private testservice3: TestService3,
private testservice3: TestService4
) {
this.loading = true;
this.getApplicationLogic()
.then(() => {
this.loading = false;
})
}
public getApplicationLogic() {
return new Promise((resolve, reject) => {
testservice1.getTest()
.then(
res => {
testservice1.setTestConfig(res);
return this.testservice2.getTest2();
},
msg => {
throw new Error(msg)
})
.then(
res => {
testservice2.setTestConfig(res);
return this.testservice3.getTest3();
},
msg => {
throw new Error(msg)
})
.then(
res => {
testservice3.setTestConfig(res);
resolve();
},
msg => {
throw new Error(msg)
})
});
}

您可以通过注入Injector而不是导致循环依赖的服务之一来解决循环依赖

private testservice1:Testservice1;
constructor(/*private testservice1:Testservice1*/ injector:Injector) {
setTimeout(() => this.testservice1 = injector.get(Testservice1));
}

我不知道你的代码有多复杂。但是,如果你跨越了任何循环依赖关系,那么你就可以应用它。

Generaly我用一个通用的appstate服务来构建服务,该服务保存全局设置(如后端服务器url),一个处理通用http请求的http服务,如

export class MyHttpService{
constructor(
private http: HttpClient,
private app: AppstateService,
private log: LogService
) { }
getRest<T>(api: string)  {
let opts = this.getOptions();
return this.http.get<T>(this.app.backurl + "/api/v1/" + api, opts);
}

以及实现高级api(如)的api服务

export class MyapiService {
constructor(private myhttp: MyHttpService) {}
GetOperations(pt_id: number) {
this.myhttp.getRest<DashboardOperations>( "GetDashboardOperations?pt_id=" 
+ pt_id ).pipe(map(resp=> resp.data));
}

最后一个组件只处理api服务,通过subscribe获取数据。

如果你不希望你的应用程序每次刷新信息时都能获取所有数据,你可以考虑使用pouchdb在本地存储数据,并将其与服务器同步(请参阅https://www.sitepoint.com/offline-web-apps-service-workers-pouchdb/)

您有两个问题:

  1. 如何在应用程序启动时从API加载数据。为此,您需要使用APP_INITIALIZER令牌。这里有官方文档,这里有教程说明。

  2. 避免循环依赖。我认为你的主要服务不能(也不应该)重复使用。从本质上讲,API调用应该是异步的,但您似乎正在尝试按特定顺序运行它们。当你说"每当我从另一个服务导入这个主服务时"时,你想做什么还不太清楚——以你的代码为例,显然没有一个testservices1..4可以导入main。因此,如果您有一些新的服务器(testservice5)需要首先加载1..4,那么testservice5可以导入Main,然后自己完成工作。例如,即使testservice5进行与testservice1相同的API调用(当然,这意味着您将有代码重复)。

(2)的一个更好的解决方案是,不要设计以特定的预定义顺序执行服务,而是允许每个服务彼此独立地启动,存储数据,并具有某种全局跟踪器,该跟踪器在每个服务完成时更新(返回数据)。

例如,在应用程序启动时,您希望完成4项服务。激发第一个,结果是将标志更新为1并激发一个事件。您的第二个服务侦听该事件并运行。结果是,您将标志更新为2,然后再次激发事件。服务3监听该事件并运行、更新标志等。

通过这种方式,您可以在启动时按定义的顺序使用所有4个服务,但仍然将每个服务作为一个独立的自包含的"东西",稍后在应用程序运行时可以重复使用。

相关内容

  • 没有找到相关文章

最新更新