ChatGPT解决这个技术问题 Extra ChatGPT

什么是“装饰器”,它们是如何使用的?

我很好奇 AngularJS 中的装饰器到底是什么。除了 AngularJS documentation 中的简介和 youtube video 中的简短(尽管很有趣)提及外,没有太多关于装饰者的在线信息。

正如 Angular 的人所说,装饰器是:

服务的装饰,允许装饰器拦截服务实例的创建。返回的实例可能是原始实例,也可能是委托给原始实例的新实例。

我真的不知道这意味着什么,我不确定你为什么要将这个逻辑与服务本身分开。例如,如果我想在不同的条件下返回不同的东西,我只需将不同的参数传递给相关函数或使用另一个共享该私有状态的函数。

我仍然是一个 AngularJS 菜鸟,所以我确信这只是我养成的无知和/或坏习惯。


t
tamakisquare

$provide.decorator 的一个很好的用例是当您需要对您的模块所依赖的某些第三方/上游服务进行较小的“调整”时,同时保持服务完好无损(因为您不是服务的所有者/维护者)。 Here 是 plunkr 上的演示。


很棒的例子。我实际上想知道如何在不干预第三方模块功能的情况下扩展它们
装饰器实际上是否对服务的所有实例进行了类型化,或者它们是否仅限于装饰它们的模块?换句话说,假设我有一个模块 A,它装饰了模块 B 的服务。然后我有模块 C,它依赖于模块 A 和模块 B。在模块 C 内部,来自模块 B 的服务是原始版本还是装饰版本?
@JonJaques - 这是一个很好的问题。我没有遇到过这样的情况。如果我猜的话,模块 C 看到的服务版本应该是来自模块 A 的修饰版本,但在我自己尝试之前我不能肯定地说。你为什么不写一个简单的 plunkr/jsffidle 并尝试一下。如果您能与我们分享您的发现,那就太好了。干杯。
@JonJaques - 无法抑制我的好奇心,所以我在原始示例中添加了几行以找到您问题的答案,link。总之,我之前评论中的猜测是对的。
工厂、服务等都是单例的(因为它们是提供的),所以一旦装饰,总是装饰。
S
StayOnTarget

装饰器允许我们分离横切关注点并允许服务保留单一职责原则,而无需担心“基础设施”代码。

装饰器的实际用途:

缓存:如果我们有一个服务可能会进行昂贵的 HTTP 调用,我们可以将服务包装在一个缓存装饰器中,该装饰器在进行外部调用之前检查本地存储。

调试/跟踪:根据您的开发/生产配置进行切换,使用调试或跟踪包装器装饰您的服务。

节流:将频繁触发的调用包装在一个去抖动的包装器中。例如,允许我们轻松地与速率受限的服务进行交互。

在所有这些情况下,我们将服务中的代码限制为其主要职责。


D
Daiwei

decorator 可以拦截由 factory, service, value, provider 创建的服务实例,并提供更改某些 instance(service) 的选项,否则这些 instance(service) 是不可配置的/带有选项。

它还可以提供用于测试目的的模拟实例,例如 $http


值得注意的是,您还可以将 directive 定义覆盖为 presented by Ben Nadel
这是官方 Angular 文档中的参考:https://docs.angularjs.org/guide/decorators
G
Gurupreet

简单来说,我们可以说它就像一个扩展方法。对于前。我们有一个类,它有两个方法,在运行时我们想在其中添加更多方法,然后我们使用装饰器。

我们不能将 $provide.decorator 与常量一起使用,因为我们无法更改它们正在提升只读属性的常量。


S
SAMUEL

简而言之,装饰器可以描述如下:-

装饰器函数拦截服务的创建,允许它覆盖或修改服务的行为。

它通过角度使用 $provide 服务并修改或替换另一个服务的实现

$provide.decorator('service to decorate',['$delegate', function($delegate) {
  // $delegate - The original service instance, 
  //             which can be replaced, monkey patched, 
  //             configured, decorated or delegated to. 
  //             ie here what is there in the 'service to decorate'

  //   This function will be invoked, 
  //   when the service needs to be provided 
  //   and should return the decorated service instance.
  return $delegate;
}]);

例子:

$provide.decorator('$log', ['$delegate', function($delegate) {
  // This will change implementation of log.war to log.error
  $delegate.warn = $delegate.error; 
  return $delegate;
}]);

应用

除了@JBland 答案。

应用程序范围的区域设置:- 您可以在此处找到示例

通过角度服务更改服务的默认行为和现有实现:-您可以在此处找到示例

一个函数在不同环境中的切换行为。