angularjs:创建闪烁消息的系统

时间:2013-10-28 09:37:16

标签: javascript angularjs

我的 AngularJS 应用程序具有以下简化行为:

我创建了一个名为server的工厂的服务模块。这个server模块处理我与websocket服务器的通信。当此websocket连接中发生事件时,我想在MainController中显示一条闪烁的消息。

我的服务:

return function init() {
  ws = new WebSocket(...);
  ws.onopen(function () {
    $rootScope.$broadcast("flash", "websocket connected");
  });
};

我的观点:

<article ng-controller=MainController ng-init=init()>
  <section ng-show="flash.length > 0">
    <p ng-repeat="message in flash">
      {{ message }}
    </p>
  <section>
  <section ng-view>
  ...
</article>

我的控制器:

function MainController ($rootScope, $scope, server) {
  $scope.init = function () {
    $scope.flash = [];
    server.init(); 
  };
  $scope.on("flash", function (event, flash) {
    $scope.flash.push(flash);
    // $scope.$apply("$scope.flash"); <-- if I uncomment this line, I get the error...
    console.debug($scope.flash[$scope.flash.length -1]);
  });
};

如果我运行此代码,我会在websocket连接上获得调试消息,但是如果我单击按钮f.e,则仅应用对flash数组的更改。或者如果我调用$apply函数。 后者导致“应用已在进行中”的错误。经过一些研究,我确信,调用$apply是没有必要的。

那么:如何以一种立即通知视图变化的方式改变flash数组?

2 个答案:

答案 0 :(得分:2)

嗯,您需要从WebSocket代码中调用$apply。 WebSocket事件发生在Angular之外,所以这是必要的。如果您的$apply导致摘要已在进行中,那么其他一些代码是否也可以发送“闪存”消息?

我建议您将$apply调用放入WebSocket代码中:

return function init() {
  ws = new WebSocket(...);
  ws.onopen(function () {

    $rootScope.$apply(function() {
      $rootScope.$broadcast("flash", "websocket connected");
    });

  });
};

<强>附加

如果你真的需要将$apply放在控制器中(我不建议这样做),那么你可以试试“安全应用”模式:

$scope.$safeApply = function (fn) {
  var phase = this.$root.$$phase;
  if (phase == '$apply' || phase == '$digest') {
    if (fn && (typeof (fn) === 'function')) {
      fn();
    }
  } else {
    this.$apply(fn);
  }
};

然后,当您收到“flash”事件时,您可以这样做:

$scope.$safeApply(function() {
  $scope.flash.push(flash);
});

同样,我认为这种方法将$apply的知识放在了错误的地方,但是有可能实现你的目标。

答案 1 :(得分:0)

我在相关so-post中找到了答案。 所以我将$broadcast的电话打包成$timeout

$timeout(function () {
  $rootScope.$broadcast("flash", "websocket connected"); 
}, 50);

请发表评论如果您知道,为什么会这样?