Javascript AngularJS:服务$broadcast和$watch未在接收控制器上触发
AngularJS noob在这里,在我通往角度启蒙的道路上:) 情况如下: 我在我的模块“应用程序”中实现了一项服务“AudioPlayer”,并注册如下:Javascript AngularJS:服务$broadcast和$watch未在接收控制器上触发,javascript,angularjs,Javascript,Angularjs,AngularJS noob在这里,在我通往角度启蒙的道路上:) 情况如下: 我在我的模块“应用程序”中实现了一项服务“AudioPlayer”,并注册如下: app.service('AudioPlayer', function($rootScope) { // ... this.next = function () { // loads the next track in the playlist this.loadTrack(p
app.service('AudioPlayer', function($rootScope) {
// ...
this.next = function () {
// loads the next track in the playlist
this.loadTrack(playlist[++playIndex]);
};
this.loadTrack = function(track) {
// ... loads the track and plays it
// broadcast 'trackLoaded' event when done
$rootScope.$broadcast('trackLoaded', track);
};
}
这是“接收器”控制器(主要用于UI/表示逻辑)
在我的视图中,我显示当前轨迹信息,如下所示:
<div ng-controller="PlayerCtrl">
<button ng-click="next()"></button>
// ...
<p id="info">{{current.title}} by {{current.author}}</p>
</div>
只有在“手动”交互过程中才会打印出来
同样,如我所说,如果我在$on侦听器中添加一个console.log(当前),如下所示:
$scope.$on('trackLoaded', function(event, track) {
$scope.current = track;
console.log($scope.current);
});
这将始终正确打印
我做错了什么
(注:我在HTML5音频播放器上使用AudioJS,但我不认为这是罪魁祸首…当您有一个点击事件时,$scope会更新,如果没有该事件,您将需要使用$apply
$scope.$apply(function () {
$scope.current = track;
});
由于窥视摘要内部不安全,最简单的方法是使用
$timeout
:
$timeout(function () {
$scope.current = track;
}, 0);
回调总是在良好的环境中执行
编辑:事实上,应该在应用阶段包装的函数是
this.loadTrack = function(track) {
// ... loads the track and plays it
// broadcast 'trackLoaded' event when done
$timeout(function() { $rootScope.$broadcast('trackLoaded', track); });
};
否则就会错过广播
~~~~~~
实际上,另一种方法可能更好(至少从语义的角度来看),它在摘要周期内外都同样有效:
$scope.$evalAsync(function (scope) {
scope.current = track;
});
- 关于
$scope.$apply的优势:您不必知道自己是否处于摘要周期
- 与
相关的优点:您并不真正需要超时,而且在没有额外的$timeout
参数的情况下,您可以获得更简单的语法0
$rootScope.$applyAsync(function(){})对我有效代码>先生,您让我高兴极了。然而,我发现这样做总是有效的:$scope.current=track$作用域:$apply()代码>实际上,这会在控制台中给出一个错误:$digest已在进行中
。。。mh?您可以检查$scope.$$phase以查看是否正在更新范围,如果是这样,你不需要$apply@PierloUpitup最好将它放在$apply
函数中,因为它在try/catch/finally
中运行代码:try/catch
处理错误,finally
使用$digest
来运行代码,而不考虑错误。使用$timeout
。窥视$scope.$$阶段被视为接口中断,可能随时中断$超时保证(使用正确的参数)在$apply块中执行函数。$timeout在$apply块中执行函数。来自angular文档:用法$timeout(fn[,delay][,invokeApply]);参数fn–{function()}–应延迟其执行的函数。延迟(可选=0)–{number=}–以毫秒为单位的延迟。invokeApply(optional=true)–{boolean=}–如果设置为false,将跳过模型脏检查,否则将在$apply块内调用fn。
this.loadTrack = function(track) {
// ... loads the track and plays it
// broadcast 'trackLoaded' event when done
$timeout(function() { $rootScope.$broadcast('trackLoaded', track); });
};
$scope.$evalAsync(function (scope) {
scope.current = track;
});
// apply changes
$scope.current = track;
try {
if (!$scope.$$phase) {
$scope.$apply($scope.current);
}
} catch (err) {
console.log(err);
}