如何使用TypeScript静态注入器模式注入“$rootScope”

how do I inject `$rootScope` using TypeScript static injector pattern?

本文关键字:rootScope 注入 模式 何使用 TypeScript 静态 注入器      更新时间:2023-09-26

因此,最后,在获得一个用angular和typescript编译的大型模型后,我得到了以下运行时错误:

10angular.js:12314错误:[ng:cpws]无法复制!复制不支持窗口或作用域实例。http://errors.angularjs.org/1.4.1/ng/cpws

at angular.js:68
at copy (angular.js:857)
at copy (angular.js:932)
at copy (angular.js:888)
at Scope.$digest (angular.js:15666)
at Scope.$apply (angular.js:15935)
at bootstrapApply (angular.js:1624)
at Object.invoke (angular.js:4443)
at doBootstrap (angular.js:1622)
at bootstrap (angular.js:1642)

我没有改变任何"实现",我只是重新构造类以使用TypeScript。在我的代码中没有任何地方可以使用angular.copy(在整个应用程序的任何类中)。我的头重重地撞在墙上之后,偶然发现了这个问题。构造函数将$rootScope分配给一个局部变量(由于TS,该变量现在位于原型上)。现在,这是一种旧代码,我只使用$rootScope的引用将其用作所有使用$rootScope.broadcast(...)的视图控制器的通用事件调度器。当我使用标准的角度样板注入它时,它曾经工作得很好,我可以重构它…

/// <reference path="../../app/reference.ts" />
class UserModel {
  roles:string;
  activeRole:string;
  errorString:string;
  loginAttemptEmailValue:string;
  successString:string;
static $inject = ['utils', '$rootScope','$q', '$cookies', '$http','settings', '$location'];
  constructor(u,r,q,c,h,s,l) {
    this.utils = u;
    this.rootScope = r; // <---- the problem. comment-out this line and it works.
    this.q = q;
    this.cookies = c;
    this.http = h;
    this.settings = s;
    this.location = l;
  }
...
angular.module('App').service('userModel', UserModel );

但这让我担心当我转换控制器时,我会在注入$scope时遇到同样的问题。

所以,我的问题是,如何使用TypeScript静态注入器模式正确地注入$scope,而不会出现这种可怕的复制错误?

我尝试创建一个类级静态作用域变量,但在尝试分配给静态类型时,当然会出现左侧赋值错误。

更新:这是透明的js。

var UserModel = (function () {
    function UserModel(u, r, q, c, h, s, l) {
        var _this = this;
        this.utils = u;
        this.rootScope = r;
        this.q = q;
        this.cookies = c;
        this.http = h;
        this.settings = s;
        this.location = l;
    }
    UserModel.prototype.hasActiveRole = function (val) {
        if (this.activeRole === val) {
            return true;
        }
        return false;
    };
    //...other implementation...
    UserModel.$inject = ['utils', '$rootScope', '$q', '$cookies', '$http', 'settings', '$location'];
    return UserModel;
})();
angular.module('App').service('userModel', UserModel);

所以,在这里回答我自己的问题,如果其他人撞到了同一堵砖墙。我认为这种情况可能是Angular错误,或者缺少关于将$rootScope分配给服务中的局部变量的文档。

注入$scope$rootScope并分配给本地引用属性似乎很好,在控制器中,但在服务中则不然。我还注意到,您根本无法将$scope导入到服务中,也许angular团队也打算阻止注入$rootScope,但却忽略了这一点。

这个错误本身令人费解;我最好的猜测是,有一个来自编译的工件(在Angular的内部),其中服务的实例化试图深度复制$rootScope属性,而不是浅复制,当且仅当它被分配给服务对象上的属性时。

显然,您正试图深入观察类的整个实例。如果该对象的某个属性指向范围实例,则不应该执行此操作。如果你仍然想这样做,你可以尝试使用getter函数而不是普通的属性:this.getRootScope = () => $rootScope,它可能会起作用,但听起来仍然不是一个好主意。因为出于性能原因,当你深入观察某个东西时,你希望被观察的对象尽可能小。如果您只想检测某些数据中的更改,那么同时查找注入的服务中的更改是否有意义?很明显,您将错误的对象传递给$watch

(顺便说一句,我建议使用ngAnnotate,而不是手工编写static $inject...。)

也有同样的问题。这就是

at Scope.$digest (angular.js:15666)

您将UserModel传递给angular作为服务,并在每个公共财产上添加angular手表,包括所有这些

this.utils = u;
this.rootScope = r;
this.q = q;
this.cookies = c;
this.http = h;
this.settings = s;
this.location = l;

因此,当$digest启动时,它试图将价值保存为最后一个

watch.last = watch.eq ? copy(value, null) : value;

和copy()发生:)由于而出错

if (isWindow(source) || isScope(source)) {
  throw ngMinErr('cpws',
    "Can't copy! Making copies of Window or Scope instances is not supported.");
}

我用存储类的rootScope的外部变量临时解决了这个问题

let rootScope: ng.IRootScopeService;
class Settings() {
  static $inject = [
    '$rootScope'
  ];
  constructor($rootScope: ng.IRootScopeService) {
    rootScope = $rootScope;
  }
}

稍后将用RxJs Observables 取代$rootScope作为pub/sub的使用