我很难处理可观察对象和分布式API。我有一个包含很多行的表,对于每一行,我都需要使用单独的域服务上的单独的API来获取该行的“状态”。显而易见的解决方案是像这样预先加载所有内容:
我有10行,所以我将10个模型存储在myArray:Model[]
之类的数组中。然后,我可以订阅一个HTTP请求以获取这些模型并将它们存储在此数组的组件中。该请求返回后,我可以遍历每个Model
并执行另一个请求以获取每个模型的“状态”。这将需要我执行以下操作:1)用Model
属性对Status
域模型类进行卷积,然后在状态调用中执行另一个.subscribe
,这将允许我设置{{1 }}属性。现在,我终于可以将表格整体呈现。或2)我可以有第二个数组,例如Status
,其中包含我所有myStatuses:StatusModel[]
的所有状态,然后在表中执行Model
,这必须找到正确的运行时状态。
这感觉像一堆代码,可以做一些相当简单的事情。
我本以为我无法通过使用Observable和异步管道来添加所有这些额外的状态...但是,当我尝试将异步管道与getStatusForModel(model)
之类的调用一起使用时,会返回一个{{1 }}我的浏览器进入了无限循环,因为它每次都返回getStatusAsync(model)
且更改检测迫使视图不断更新。
基本上,我不能弄清楚执行异步操作的预期用途是什么,而不必在组件中保持如此多的状态。如果我什至无法返回实际的Promise<StatusModel>
并且仅通过更改检测而不是Promise对象本身来跟踪返回的值,那么Promise
的意义是什么?
我觉得Angular中的Observables和async所增加的代码和复杂性超出了应有的程度。我是在做错什么,还是这只是现在使用可观察物和诺言的现实?
答案 0 :(得分:2)
我很同情必须使用如此繁琐的API。
是的,如果您只需要在模板中使用异步管道,则“解包”最简单的方法就是使用异步管道。
是的,只要异步管道接收到另一个Observable实例,它就会重新订阅。那是因为angular无法知道新的可观察到的等效于旧的。
顺便说一句,在更改检测到的表达式中调用函数通常是令人讨厌的,因为该函数是在每次更改检测运行期间执行的(是的,即使参数未更改; angular无法知道返回值仅取决于参数)。
因此,您不应在更改检测期间创建可观察到的状态。
也就是说,我会做类似的事情
models = this.fetchModels().pipe(map(
models => models.map(
model => {...model, status: this.fetchStatus(model)}
)
));
在模板中
<tr *ngFor="let model of models | async">
<td>{{model.name}}</td>
<td>{{model.status | async}}</td>
</tr>
请注意,每当model
在表中可见时,此解决方案将导致发出新的API请求。这可能比您想要的更多。您可以通过使用适当的rxjs运算符或通过手动输入打字稿代码中的状态来展开可观察的状态,来控制重新加载状态的频率。
附录:这是否违反DDD?
您问:
我不想这样做的原因是在正确的DDD中,您应该具有相互分离的域对象。
我认为这不是一个明确的方法:DDD存储库返回集合,而不是单个实体。
在真正的SOA中,我在一个服务上有一个订购API,在第二个服务上有一个发票API。然后,我将从Order API获取我的订单列表,然后随后请求获取每个订单的发票。通常,我认为在UI上混合模型很不好-这意味着当后端模型根本不执行此操作时,我不必强制使用Order.InvoiceStatus属性。这是耦合域模型。
在DDD中,每个有界上下文中都有一种无处不在的语言。
您似乎认为您的UI和后端在同一个有界上下文中,但是如果是这样,为什么它们使用结构上不同的模型?为什么发票状态显示在订单表中,却存储在发票表中?
在DDD中,用户界面和后端之间关于域结构的这种紧张关系可以通过两种方式解决:
共享内核:用户界面和后端在通用模型上达成共识。型号已更改,因此适合所有人。在您的情况下,这意味着如果UI需要订单上的发票状态,则后端应返回订单上的发票状态。
反腐败层:UI和后端具有不同的模型,并且模型通过边界时会发生转换。也就是说,将域模型转换为更适合API访问期间的UI的视图模型。
您将必须决定哪种方法更适合您的应用程序。
我希望我可以将它们分开,但是听起来Angualr希望它起作用的方式是引入像OrderViewModel这样的第三种模型,该模型具有对Order和Invoice的处理(以及其他模型) 。这听起来对吗?
从技术上讲,角度并不关心数据模型的结构。它可以将数据绑定到几乎所有东西。
但是从最佳实践的角度来看,我发现重要的一点是,每个层都可以使用适合它的模型。因此,是的,如果您不能使用共享内核,我建议您使用(轻型)防破坏层。