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

IT技术 javascript angularjs decorator angularjs-decorator
2021-03-16 22:34:55

我很好奇 AngularJS 中的装饰器到底是什么。除了AngularJS 文档中的简介和youtube 视频中的简短(尽管很有趣)提及之外,关于装饰器的在线信息并不多

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

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

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

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

5个回答

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

很棒的例子。我实际上想知道如何扩展第三方module功能而不干预它们
2021-04-15 22:34:55
@JonJaques - 这是一个很好的问题。我没有遇到过这种情况。如果我猜的话,module C 看到的服务版本应该是module A 中的装饰版本,但在我自己尝试之前我不能肯定地说。为什么不编写一个简单的 plunkr/jsffidle 并进行试验。如果您能与我们分享您的发现,那就太棒了。干杯。
2021-04-16 22:34:55
装饰器实际上是对服务的所有实例进行鸭嘴式输入,还是仅将其作用域限定为装饰它们的module?换句话说,假设我有module A 装饰module B 的服务。然后我有依赖module A 和module B 的module C。在module C 内部,来自module B 的服务是原始版本还是装饰版本?
2021-05-06 22:34:55
@JonJaques - 无法抑制我的好奇心,所以我在原始示例中添加了几行以找到您问题的答案,链接总之,我之前评论中的猜测是对的。
2021-05-11 22:34:55
工厂、服务等是单身人士(因为他们提供),所以一旦装饰,总是装饰。
2021-05-13 22:34:55

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

装饰器的实际用途:

  • 缓存:如果我们有一个服务可能会进行潜在的 HTTP 调用,我们可以将服务包装在缓存装饰器中,该装饰器在进行外部调用之前检查本地存储。
  • 调试/跟踪:根据您的开发/生产配置有一个开关,它用调试或跟踪包装器装饰您的服务。
  • 节流:将频繁触发的调用包装在去抖动包装器中。例如,允许我们轻松地与限速服务进行交互。

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

decorator可以拦截由创建的服务实例factory, service, value, provider,并提供选项来更改一些instance(service)否则无法配置/使用选项。

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

这是官方 Angular 文档中的参考:https : //docs.angularjs.org/guide/decorators
2021-04-19 22:34:55
值得注意的是,您还可以覆盖Ben Nadel 提出的directive定义
2021-04-30 22:34:55

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

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

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

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

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

$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 的回答。

  • 应用程序范围的语言环境设置:-

    你可以在这里找到一个例子

  • 通过角度服务更改服务的默认行为和现有实现:-

    你可以在这里找到一个例子

  • 功能在不同环境中的切换行为。