我知道AngularJS会将一些代码运行两次,有时甚至更多,比如$watch events,不断检查模型状态等等。

然而我的代码:

function MyController($scope, User, local) {

var $scope.User = local.get(); // Get locally save user data

User.get({ id: $scope.User._id.$oid }, function(user) {
  $scope.User = new User(user);
  local.save($scope.User);
});

//...

执行两次,将2条记录插入到我的DB中。我显然还在学习,因为我已经用我的头撞它很多年了!


当前回答

由于不同的原因,我已经有了这个双重初始化。对于我的应用程序中的一些路由转换,我想强制滚动到接近页面顶部(例如在分页搜索结果中……)单击next会将您带到第2页的顶部)。

我通过在$viewContentLoaded上的$rootScope $中添加一个侦听器来实现这一点(基于某些条件)

$location.hash('top');

无意中,这导致我的路由被重新评估,控制器被重新初始化

其他回答

特此补充,以供参考:

在同样运行在页面上的指令中引用控制器也可能导致双控制器代码执行。

e.g.

return {

            restrict: 'A',
            controller: 'myController',
            link: function ($scope) { ....

当你也有ng-controller="myController"在你的HTML

在我的例子中,我发现使用相同控制器的两个视图。

$stateProvider.state('app', {
  url: '',
  views: {
    "viewOne@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/one.tpl.html'
    },
    "viewTwo@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/two.tpl.html'
    }
  }
});

在这里加上我的案例:

我使用angular-ui-router和$state。Go ('new_state', {foo: "foo@bar"})

一旦我将encodeURIComponent添加到参数中,问题就解决了:$state。go('new_state', {foo: encodeURIComponent("foo@bar")})。

发生了什么事? 参数值中的“@”字符不允许出现在url中。因此,angular-ui-router创建了我的控制器两次:在第一次创建时,它传递了原始的“foo@bar”,在第二次创建时,它将传递编码版本“foo%40bar”。一旦我像上面那样显式地对参数进行编码,问题就解决了。

我一直在用AngularJS 1.4 rc构建这个问题,然后意识到上面的答案都不适用,因为在撰写本文时,它起源于Angular 1.4和Angular 2的新路由器库。因此,我要在这里提醒那些可能正在使用新的Angular路由库的人。

基本上,如果一个html页面包含一个ng-viewport指令来加载你的应用程序的部分,通过点击ng-link中指定的超链接将导致相关组件的目标控制器被加载两次。细微的区别在于,如果浏览器已经加载了目标控制器,那么重新单击相同的超链接只会调用该控制器一次。

还没有找到可行的解决方案,尽管我相信这个行为与shaunxu提出的观察是一致的,希望这个问题能在未来的新路由库构建中以及AngularJS 1.4版本中得到解决。

The problem I am encountering might be tangential, but since googling brought me to this question, this might be appropriate. The problem rears its ugly head for me when using UI Router, but only when I attempt to refresh the page with the browser refresh button. The app uses UI Router with a parent abstract state, and then child states off the parent. On the app run() function, there is a $state.go('...child-state...') command. The parent state uses a resolve, and at first I thought perhaps a child controller is executing twice.

在URL附加散列之前一切正常。 www.someoldwebaddress.org

一旦url被uirouter修改了, www.someoldwebaddress.org / childstate

...然后当我用浏览器刷新按钮刷新页面时,$stateChangeStart会触发两次,每次都指向childstate。

父状态的解析是触发两次的东西。

也许这只是一种拼凑;无论如何,这似乎为我消除了问题:在第一次调用$stateProvider的代码区域,首先检查window.location.hash是否为空字符串。如果是,一切都好;如果不是,则将window.location.hash设置为空字符串。那么,$state似乎只会尝试去某个地方一次,而不是两次。

此外,如果你不想依赖于应用程序的默认run和state.go(…),你可以尝试捕获散列值,并使用散列值来确定页面刷新前你所处的子状态,并在代码中设置state.go(…)的区域添加一个条件。