如何使用TypeScript静态注入模式注入`$ rootScope`?

时间:2015-11-19 20:45:50

标签: javascript angularjs angularjs-scope typescript

所以,最后在使用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,现在在原型上)。现在,这是一种旧代码,我只使用ref to $ 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);

3 个答案:

答案 0 :(得分:1)

所以,在这里回答我自己的问题,其他人应该碰到同样的砖墙。我认为这种情况可能是Angular错误或缺少有关将$rootScope分配给服务中的本地变量的文档。

注入$scope$rootScope并分配给本地参考资产似乎工作正常,在控制器中但不是服务。我还注意到你根本不能$scope导入到服务中,也许有角度的团队也意味着也会阻止注入$rootScope但忽略这样做。

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

答案 1 :(得分:1)

显然,您正在尝试深入观察班级的整个实例。如果此对象的某个属性指向范围实例,则您不应该这样做。如果你们都希望这样做,你可以尝试使用getter函数而不是普通的属性:this.getRootScope = () => $rootScope,这可能有效,但听起来并不是一个好主意。因为性能原因,当您深入观察某些内容时,您希望观察对象尽可能小。如果您只想检测某些数据中的更改,是否有必要同时查找注入服务中的更改?显然,您将错误的对象传递给$watch

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

答案 2 :(得分:0)

有同样的问题。就是这件事

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

您将UserModel传递给angular作为服务,并在每个公共属性上增加了角度,包括所有这些

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

因此,当$ digest开始时,它会尝试save value as last

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

和copy()发生:),错误为because of

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