gpt4 book ai didi

angular - 在Angular服务中频繁使用BehaviorSubject是一个危险信号吗?

转载 作者:搜寻专家 更新时间:2023-10-30 21:25:41 25 4
gpt4 key购买 nike

我正在使用angular编写一个应用程序,发现自己经常使用这种模式:

@Injectable(...)
export class WidgetRegsitryService {
private readonly _widgets: BehaviorSubject<Widget[]> = new BehaviorSubject([]);
public get widgets() { return this._widgets.value; }
public readonly widgets$ = this._widgets.asObservable();

public add(widget: Widget) {
const old = this._widgets.value.slice();
old.push(widget);
this._widgets.next(old);
}
}

许多服务机构将拥有3-5个或更多这样的公共获取者和私人支持对象。这种情况经常发生,以至于代码感觉非常冗长和重复。那么:a)有没有一个干巴巴的方法来做这件事,b)我是否在这里误用了可观测数据?

最佳答案

我正在使用angular编写一个应用程序,发现自己经常使用这种模式:
您显示的模式与状态存储非常相似,例如;ReduxNgRXNGXS。不同的是,您将存储、选择器和还原器放在一个类中。
在一个地方拥有一切都是有好处的,但是如果你每次启动新的服务时都必须重新编写一个新的商店,那么这就可以解释为什么你会说“它发生得太多以至于代码感觉非常冗长和重复”。
这没有什么问题,互联网上有很多博客文章试图用尽可能少的代码行编写redux克隆。我的观点是,人们总是在做你一直在做的事情。

private readonly _widgets: BehaviorSubject<Widget[]> = new BehaviorSubject([]);

上面是州经理的商店。它是一个包含当前状态并对该状态发出更改的可观察对象。
public get widgets() { return this._widgets.value; }

上面是状态管理器的快照。这允许您在不必订阅的情况下对存储区执行特定计算,但与使用快照的其他状态存储区一样,可能会出现竞争条件问题。您也不应该直接从模板访问它,因为它将触发“表达式在被选中后已更改”错误。
public readonly widgets$ = this._widgets.asObservable();

上面是商店的选择器。商店通常有许多选择器,允许应用程序的不同部分侦听特定主题的商店更改。
public add(widget: Widget) {
const old = this._widgets.value.slice();
old.push(widget);
this._widgets.next(old);
// above can be rewritten as
this._widgets.next([...this.widgets, widget]);
}

我们在州立商店图书馆里没有上述内容。以上分为动作和减速器两部分。该操作通常包含有效负载(在您的例子中是一个小部件),而reducer执行修改存储的工作。
当我们使用actions和reducer时,它将存储应该如何改变的业务逻辑与读取当前状态、更新状态和保存下一个状态的问题分离开来。你的例子很简单。在一个必须订阅、修改和发出更改的大型应用程序中,当您只想切换布尔标志时,这些更改可能会成为开销较大的样板代码。
许多服务机构将拥有3-5个或更多这样的公共获取者和私人支持对象。这种情况经常发生,以至于代码感觉非常冗长和重复。
你正在进入重新发明轮子的领域。
在我看来,你有两个可能的选择。创建自己的状态存储框架,它会让您感觉更舒服,或者从上面列出的一个库中使用现有的状态存储。我们不能告诉你该走哪条路,但我做过很多角度的项目,我可以告诉你没有正确的答案。
真正让源代码感觉不那么冗长和重复的是高度自以为是的。使它不再冗长的事情可能有一天会成为一个设计错误困扰着你,重复的源代码是痛苦的,但有一天你会感激你可以修改一行代码,而不影响你的源代码的其他领域。
a)有没有干的方法可以做到,并且
消除源代码的唯一方法是将状态管理的实现与业务逻辑解耦。这是我们讨论如何为状态存储创建一个好的设计模式的地方。
你用选择器吗?
你用动作吗?
你用减速器吗?
你希望这些东西在哪里(在它们自己的文件中,或者服务的方法中?)。您希望如何命名它们,是否应重新使用它们或为每个边缘案例创建新的名称?
很多问题都是个人的选择。
我可以使用 NGXS作为示例重写您的示例,但这对您来说可能并不枯燥,因为框架需要复杂才能有用。我可以告诉你,当你需要做一些你以前没有做过的事情时,更容易阅读NGX的文档,然后试着自己发明,并冒着错误的风险。这并不意味着ngxs总是正确的,但至少你可以抱怨这不是你的错:)
@State<Widget[]>({
name: 'widgets',
defaults: []
})
export class WidgetState {
@Action(AddWidgetAction)
public add(ctx: StateContext<Widget[]>, {payload}: AddWidgetAction) {
ctx.setState([...ctx.getState(), payload]);
}
}

@Component({...})
export class WidgetsComponent {
@Select(WidgetState)
public widgets$: Observable<Widget[]>;

public constructor(private _store: Store) {};

public clickAddWidget() {
this._store.dispatch(new AddWidgetAction(new Widget()));
}
}

b)我是否误用了可观测数据?
绝对不会误用可见光。您很清楚为什么服务应该是无状态和被动的。我认为你只是在自己发现国有商店的价值,现在你正在寻找更容易利用它们的方法。

关于angular - 在Angular服务中频繁使用BehaviorSubject是一个危险信号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56291934/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com