Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS:服务$broadcast和$watch未在接收控制器上触发_Javascript_Angularjs - Fatal编程技术网

Javascript AngularJS:服务$broadcast和$watch未在接收控制器上触发

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

AngularJS noob在这里,在我通往角度启蒙的道路上:)

情况如下:

我在我的模块“应用程序”中实现了一项服务“AudioPlayer”,并注册如下:

 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);
}