Javascript 角度运行块,$rootScope.$on和$state
当我尝试在run块中创建eventhandler时,出现了一个奇怪的问题。要解释这个问题有点困难,部分原因是我不明白发生了什么,但我会尽我所能。这是用打字稿写的 我有以下运行块:Javascript 角度运行块,$rootScope.$on和$state,javascript,angularjs,javascript-events,typescript,angular-ui-router,Javascript,Angularjs,Javascript Events,Typescript,Angular Ui Router,当我尝试在run块中创建eventhandler时,出现了一个奇怪的问题。要解释这个问题有点困难,部分原因是我不明白发生了什么,但我会尽我所能。这是用打字稿写的 我有以下运行块: angular.module("myapp") .run(($rootScope, StateChangeStartHandler) => { $rootScope.$on("$stateChangeStart", StateChangeStartHandler.handler); }); St
angular.module("myapp")
.run(($rootScope, StateChangeStartHandler) => {
$rootScope.$on("$stateChangeStart", StateChangeStartHandler.handler);
});
StateChangeStartHandler是一个简单的angular服务,具有一个名为handler的函数,用于处理$stateChangeStart事件。处理程序服务如下所示:
class StateChangeStartHandler {
private AuthService;
private $rootScope;
private AUTH_EVENTS;
constructor(AuthService, $rootScope, AUTH_EVENTS
// Everything breaks if I comment in the following line
//, $state
) {
this.AuthService = AuthService;
this.$rootScope = $rootScope;
this.AUTH_EVENTS = AUTH_EVENTS;
}
handler(event, next) {
if (!this.AuthService.isLoggedIn() && next.name != "root.login") {
event.preventDefault();
this.$rootScope.$broadcast(this.AUTH_EVENTS.notAuthenticated);
}
}
}
angular.module("myapp")
.service("StateChangeStartHandler", StateChangeStartHandler);
angular.module("myapp")
.run(($rootScope, StateChangeStartHandler) => {
$rootScope.$on("$stateChangeStart", StateChangeStartHandler.handler());
});
我是用TDD实现的。我编写了一个测试,验证是否在$state上调用了go。当我进入课堂去实现它时,我面临着这个问题。当我在StateChangeStartHandler中注入$state时,突然所有使用$rootScope的测试。$apply()说AuthService.isLoggedIn不是一个函数
我怀疑$rootScope.$apply()触发了$stateChangeStart,然后发生了一些奇怪的事情
更新1:
一个看似无关的测试突然失败的例子:
Chrome 45.0.2454 (Mac OS X 10.10.5) Authentication service login(email, password) should be defined FAILED
TypeError: this.AuthService.isLoggedIn is not a function
at StateChangeStartHandler.handler (/Users/blacksails/repos/avalonia/priv/static/js/app.js:305:31)
at Scope.$broadcast (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:16311:28)
at Object.transitionTo (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:50779:24)
at Array.<anonymous> (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49896:18)
at Object.invoke (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:4584:17)
at handleIfMatch (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49386:28)
at /Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49441:18
at check (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49557:23)
at update (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49566:13)
at Scope.$broadcast (/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:16311:28)
Chrome 45.0.2454(Mac OS X 10.10.5)身份验证服务登录(电子邮件、密码)应定义失败
TypeError:this.AuthService.isLoggedIn不是函数
StateChangeStartHandler.handler(/Users/blacksails/repos/avalonia/priv/static/js/app.js:305:31)
范围:$broadcast(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:16311:28)
在Object.transitiono(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:50779:24)
在阵列上。(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49896:18)
在Object.invoke(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:4584:17)
在handleIfMatch(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49386:28)
at/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49441:18
检查时(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49557:23)
更新时(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:49566:13)
范围:$broadcast(/Users/blacksails/repos/avalonia/priv/static/js/libraries.js:16311:28)
试试这些:
angular.module("myapp")
.run(($rootScope, StateChangeStartHandler) => {
$rootScope.$on
("$stateChangeStart",StateChangeStartHandler.handler.bind(StateChangeStartHandler);
});
我终于解决了。我不太确定技术细节,但我认为这与angular lazy如何加载服务有关。以下步骤解决了我的问题。而不是像这样引用
StateChangeStartHandler
中的函数handler
angular.module("myapp")
.run(($rootScope, StateChangeStartHandler) => {
$rootScope.$on("$stateChangeStart", StateChangeStartHandler.handler);
});
我让它成为这样的一个获得者:
class StateChangeStartHandler {
private AuthService;
private $rootScope;
private AUTH_EVENTS;
constructor(AuthService, $rootScope, AUTH_EVENTS
// Everything breaks if I comment in the following line
//, $state
) {
this.AuthService = AuthService;
this.$rootScope = $rootScope;
this.AUTH_EVENTS = AUTH_EVENTS;
}
handler(event, next) {
if (!this.AuthService.isLoggedIn() && next.name != "root.login") {
event.preventDefault();
this.$rootScope.$broadcast(this.AUTH_EVENTS.notAuthenticated);
}
}
}
angular.module("myapp")
.service("StateChangeStartHandler", StateChangeStartHandler);
angular.module("myapp")
.run(($rootScope, StateChangeStartHandler) => {
$rootScope.$on("$stateChangeStart", StateChangeStartHandler.handler());
});
我将函数保存在
StateChangeStartHandler
中的一个字段中,然后handler
仅返回该函数。在根本不确定的情况下,我怀疑当我像第一个示例中那样传递函数时,StateChangeStartHandler
及其依赖项没有得到正确初始化。如果有人能解释更多,我会非常高兴。哪里有$apply
?为什么需要在$rootScope
上调用$apply
?通常是在地方层面上做的,我做了一些承诺测试。实际上,还有很多其他测试也失败了。我有很多使用$httpBackend的测试,所有这些似乎都在$httpBackend.verifyNoOutstandingExpectation()上失败,后者反过来调用Scope.$Digest不会更改所有失败的测试。您需要像这样调用广播:$broadcast($stateChangeStart),data)。你必须打电话给广播,说$on上发生了什么事,而不是另一种方式为什么我要广播$stateChangeStart?Angular ui router已经自动完成了。因为您是这样注册的$。我没有看到任何ui路由器设置。通过广播,您可以“调用”您在$onWell中设置的内容。通过使用$stateChangeStart,我使用ui路由器的事实是显而易见的,我还标记了问题ui路由器。