Angular 6-为什么使用@ngrx/store 而不是服务注入

我最近在用@ngrx/store 学习 Angular 6,而其中一个教程是用@ngrx/store 进行状态管理,然而,我不明白在幕后使用@ngrx/store 的好处。

例如,对于一个简单的登录和注册操作,我们可以使用 前面通过使用服务(让我们称之为 AuthService)来调用后端 api,在 AuthService 中存储“ userInfo”或“ token”,将用户重定向到“ HOME”页面,我们可以在任何组件中注入 AuthService,在那里我们需要使用 DI,它仅仅是一个文件 AuthService 处理所有事情来获取 userInfo。

现在,如果我们使用@ngrx/store,我们需要定义 动作/状态/减速器/效果/选择器,它可能需要写入4或5个文件来处理上述操作或事件,那么有时我们仍然需要使用 service,这看起来更加复杂和多余..。来调用后端 api

在另一些情况下,我甚至看到一些页面使用@ngrx/store 来存储对象或对象列表,比如网格数据。是用来存储内存的吗?

所以回到问题,为什么我们在 Angular 项目中使用@ngrx/store 优于服务注册存储?我知道它的“ 国家管理”用法,但是“国家管理”到底是什么?这是类似于事务日志的东西吗? 我们什么时候需要它?我们为什么要在前端处理呢?请随意分享您的建议或经验在@ngrx/商店区域!

35951 次浏览

我觉得你应该读读这两篇关于 Ngrx 商店的文章:

如果第一个解释了 Ngrx 商店解决的主要问题,它也引用了 React How-To 中的这句话,“这似乎同样适用于原始的 Flux,Redux,Ngrx 商店或任何一般的商店解决方案”:

你会知道什么时候你需要通量。如果你不确定你是否需要它,你不需要它。

对我来说 Ngrx 商店解决多个问题。例如,当您必须处理可观测数据时,以及在不同组件之间共享对某些可观测数据的责任时。在这种情况下,存储操作和减少器确保数据修改总是以“正确的方式”执行。

它还为 http 请求缓存提供了可靠的解决方案。您将能够存储请求及其响应,以便验证您正在发出的请求是否还没有存储响应。

第二个帖子是关于是什么使得这样的解决方案出现在 Facebook 的未读信息反问题的反应世界中。

关于在服务中存储不可见数据的解决方案。当处理常量数据时,它工作得很好。但是当一些组件需要更新这些数据时,你可能会遇到变化检测问题和不正确的更新问题,你可以用以下方法来解决:

  • 公共观察者模式可观察及下一个功能
  • Ngrx 商店

还有第三个选项,在服务中包含数据,并直接在 html 中使用服务,例如 *ngFor="let item of userService.users"。因此,当您在服务中更新 userService.users之后,添加或更新操作会自动呈现在 html 中,不需要任何可观察的事件或存储。

如果应用程序中的数据用于多个组件,那么就需要某种服务来共享数据。有很多方法可以做到这一点。

一个适度复杂的应用程序最终将看起来像一个前端后端结构,数据处理在服务中完成,通过可观察的数据暴露给组件。

在某一点上,您需要为您的数据服务编写某种类型的 API,如何获取数据进出、查询等。许多规则,比如数据的不可变性,以及定义良好的修改数据的单个路径。与服务器后端没有什么不同,但是比 api 调用快得多,响应也快得多。

您的 api 最终将看起来像许多已经存在的州管理库之一。他们的存在是为了解决困难的问题。如果你的应用程序很简单,你可能不需要它们。

我几乎只读到了 Ngrx 和其他像商店图书馆这样的 Redux 的好处,然而(在我看来)代价高昂的权衡似乎被轻而易举地忽略了。这通常是我看到的唯一原因: “ 没有使用 Ngrx 的唯一原因是你的应用程序小而简单”。这(我会说)只是不完整的推理,不够好。

以下是我对 Ngrx 的抱怨:

  • 您将逻辑分解成几个不同的文件,这使得代码难以阅读和理解。这违背了基本的代码内聚性和局部性原则。不得不跳到不同的地方去阅读一个手术是如何进行的,这是一种精神上的负担,可能会导致认知过载和精疲力竭。
  • 使用 Ngrx 时,您必须编写更多的代码,这增加了出现 bug 的可能性。更多代码-> 出现 bug 的更多地方。
  • 一个 Ngrx 商店可以成为一个垃圾场的所有东西,没有韵律或理由。它可以成为一个全球性的大杂烩的东西,没有人能够得到一个连贯的概述。它可以一直成长,直到没有人再理解它。
  • 我在 Ngrx 应用程序中看到过很多不必要的深度对象克隆,这导致了真正的性能问题。由于深度克隆了一个巨大的商店对象,我被分配工作的一个特定的应用程序需要40毫秒来保存商店中的数据。这是超过两个失去渲染帧,如果你试图达到一个平稳的60帧。因为它,每次互动都感觉很糟糕。
  • Ngrx 所做的大多数事情都可以通过使用一个基本的服务/外观模式来完成,这个模式可以从 rxjs 主题中公开可观察的内容。

只需在服务/外观上添加返回可观察内容的方法——这种方法取代了 Ngrx 的 reduce、 store 和 selector。然后将其他方法放在服务/外观上,以触发数据推送到这些可观察数据上——这些方法取代你在 Ngrx 的行为和效果。因此,不再使用 reducers + store + selector,而是使用返回可观测数据的方法。不是动作 + 效果,而是方法生成可观察的数据。数据从哪里来取决于您,您可以获取一些东西或者计算一些东西,然后使用您想要推送的数据调用 subject.next ()。

  • 使用 ngrx 所需要的 rxjs 知识将使您能够自己使用裸 rxjs。
  • 如果有几个组件依赖于某些公共数据,那么仍然不需要 ngrx,因为基本服务/外观模式已经显式地处理了这个问题。
  • 如果多个服务依赖于它们之间的公共数据,那么您只需在这些服务之间创建一个公共服务。你还是不需要 ngrx。它的服务一直到底,就像它的组件一直到底。

对我来说,Ngrx 看起来不是很好的底线。

它本质上是一个臃肿的、过度工程化的 EnterpriseTM 级别的 Rxjs Subject,而您本可以只使用良好的、古老的、值得信赖的 Rxjs Subject。听我说,孩子们,生命太短暂了,没必要这么复杂。基本生活必需品。简单的生活必需品。忘记你的烦恼和争吵。

我已经和 NgRx 合作三年多了。我在小型项目中使用它,在那里它很方便,但是不必要,我在应用程序中使用它,在那里它是完全适合的。与此同时,我有一个工作的项目没有使用它的机会,我必须说,它将从中受益。

在当前的项目中,我负责设计新的 FE 应用程序的架构。我的任务是完全重构现有的应用程序,对于相同的需求使用非 NgRx 的方式,它是错误的,难以理解和维护,没有文档。我决定在那里使用 NgRx,原因如下:

  • 应用程序在数据上有多个参与者 SSE 推动独立于用户的状态更新 行动。
  • 在应用程序开始时,我们加载大部分可用的数据 然后用 SSE 部分更新。
  • 根据多个 UI 元素启用/禁用不同的 UI 元素 来自 BE 和用户决策的条件。
  • UI 有多种变化。 BE 中的事件当前可以更改 可见的 UI 元素(对话框中的文本)甚至用户操作可能 改变 UI 的外观和工作方式(重复的对话框可以替换为 如果用户点击了某个按钮,就可以吃零食)。
  • 必须保留多个 UI 元素的状态,以便在用户离开时 网页和回去相同的内容(或更新通过 SSE)是 看得见。

正如你所看到的,要求不符合标准的 CRUD 操作网页。这种“角度”的方式给代码带来了极大的复杂性,以至于它变得超级难以维护。最糟糕的是,当我加入团队时,最初的两个成员离开时,没有任何关于定制的、非 NgRx 解决方案的文档。

现在,经过一年的重构后,我想我可以总结一下这个应用程序使用 NgRx 的利弊。

优点:

  • 应用程序更有条理,国家代表很容易理解, 按用途或数据来源分组,并且易于扩展。
  • 我们摆脱了许多工厂,立面和抽象类的损失 它们的用途。代码更轻,组件更“笨”,具有 更少来自其他地方的隐藏技巧。
  • 复杂的状态计算使用简单的效果和 选择器和大多数组件现在只需要 注入存储并分派操作或选择 同时处理多个操作时所需的状态切片。
  • 由于更新的应用程序需求,我们被迫重构 商店已经和它主要是 Ctrl + C,Ctrl + V 和一些重命名。
  • 多亏了 Redux 开发工具,它更容易调试和优化(是的 真的)
  • 这是最重要的-即使我们的国家本身是独一无二的 我们正在使用的商店管理不是。它有支持,它有 文件,并不是不可能找到解决方案的一些 互联网上的难题。
  • NgRx 是另一项你可以在简历中使用的技术:)

缺点:

  • 我的同事们是 NgRx 的新手,他们花了一些时间 适应并充分理解它。
  • 在某些情况下,我们提出了一些行动的问题 多次派遣,很难找到原因 修好它
  • 我们的影响是巨大的,这是真的。他们可以得到混乱,但这就是什么 我们有请求,如果没有这个代码 还是会在别的地方结束:)
  • 最大的问题? 操作根据字符串类型进行区分。收到 一个动作,忘了重新命名,然后砰的一声,不同的东西就出现了 发生的比你想象的要多,而且你也不知道为什么。

作为一个结论,我会说,在我们的情况下,NgRx 是一个伟大的选择。一开始是要求很高,但后来一切都感觉很自然和合乎逻辑。另外,当您检查需求时,您会注意到这是一个特殊情况。我理解反对 NgRx 的声音,在某些情况下,我会支持他们,但不在这个项目上。我们可以用“角度”的方式来做吗?当然,以前也是这样做的,但是一团糟。它仍然充满了锅炉代码,事情发生在不同的地方,没有明显的原因和更多。

任何有机会比较这两个版本的人都会说 NgRx 版本更好。

NGRX 有时有大量的文件和大量的重复代码。目前正在修复此问题。为某些 NGRX 状态管理情况制作泛型类,这些情况在 Angular 项目中非常常见,比如从后端加载寻呼机和对象