Я понимаю, что AngularJS проходит через некоторый код дважды, иногда даже больше, например, $watch
события, постоянно проверяя состояния модели и т.д.
Однако мой код:
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 записи в мою БД. Я, очевидно, все еще участвую, поскольку я уже давно натыкаюсь на эту голову!
Ответ 1
Маршрутизатор приложения указал навигацию на MyController
следующим образом:
$routeProvider.when('/',
{ templateUrl: 'pages/home.html',
controller: MyController });
Но у меня также было это в home.html
:
<div data-ng-controller="MyController">
Это дважды обработало контроллер. Удаление атрибута data-ng-controller
из HTML разрешило проблему. В качестве альтернативы, свойство controller:
могло быть удалено из директивы маршрутизации.
Эта проблема также возникает при использовании навигации с вкладками. Например, app.js
может содержать:
.state('tab.reports', {
url: '/reports',
views: {
'tab-reports': {
templateUrl: 'templates/tab-reports.html',
controller: 'ReportsCtrl'
}
}
})
Вкладка соответствующих отчетов HTML может напоминать:
<ion-view view-title="Reports">
<ion-content ng-controller="ReportsCtrl">
Это также приведет к запуску контроллера дважды.
Ответ 2
AngularJS docs - ngController
Обратите внимание, что вы также можете подключить контроллеры к DOM, объявив его в определении маршрута через службу $route. Общей ошибкой является снова объявить контроллер с помощью ng-контроллера в шаблоне сам. Это приведет к подключению и выполнению контроллера в два раза.
Когда вы используете ngRoute с директивой ng-view
, контроллер присоединяется к этому элементу dom по умолчанию (или ui-view, если вы используете ui-router). Поэтому вам не нужно будет прикреплять его снова в шаблоне.
Ответ 3
Я просто прошел через это, но проблема была отличной от принятого ответа. Я действительно оставляю это здесь для своего будущего себя, чтобы включить шаги, которые я прошел, чтобы исправить это.
Ответ 4
Просто хочу добавить еще один случай, когда контроллер может инициализировать дважды (это актуально для angular.js 1.3.1):
<div ng-if="loading">Loading...</div>
<div ng-if="!loading">
<div ng-view></div>
</div>
В этом случае $route.current будет уже установлен, когда ng-view будет инициализирован. Это вызывает двойную инициализацию.
Чтобы исправить это, просто измените ng-if на ng-show/ng-hide и все будет работать хорошо.
Ответ 5
Хотелось бы добавить для справки:
Выполнение кода двойного контроллера также может быть вызвано ссылкой на контроллер в директиве, которая также выполняется на странице.
например.
return {
restrict: 'A',
controller: 'myController',
link: function ($scope) { ....
Когда у вас также есть ng-controller = "myController" в вашем HTML
Ответ 6
При использовании angular -ui-router с Angular 1.3+ возникла проблема с представлением рендеринга дважды по маршруту перехода. Это привело к тому, что два раза исполнили контроллеры. Ни один из предлагаемых решений не работал у меня.
Однако обновление angular-ui-router
от 0.2.11 до 0.2.13 разрешило проблему для меня.
Ответ 7
У меня была такая же проблема, в простом приложении (без маршрутизации и простой ссылки на ng-controller), и мой конструктор контроллера выполнялся дважды. Наконец, я узнал, что моя проблема заключалась в следующем объявлении автозагрузки моего приложения AngularJS в моем представлении Razor
<html ng-app="mTest1">
Я также вручную загрузил его с помощью angular.bootstrap i.e.
angular.bootstrap(document, [this.app.name]);
поэтому удалив один из них, он работал у меня.
Ответ 8
Я порвал свое приложение и все его зависимости от бит над этой проблемой (подробности здесь: Приложение AngularJS запускается дважды (пробовали обычные решения..))
И, в конце концов, это была ошибка Bartang Chrome.
Разрешение в этом ответе:
![]()
Я бы настоятельно рекомендовал, чтобы первое, что было в любом списке, это отключить его для публикации перед изменением кода.
Ответ 9
Если вы знаете, что ваш контроллер непреднамеренно выполняет несколько раз, попробуйте выполнить поиск через ваши файлы для имени нарушающего контроллера, например: search: MyController через все файлы. Вероятно, он был скопирован в какой-то другой файл html/js, и вы забыли его изменить, когда вам нужно было разработать или использовать эти частичные/контроллеры. Источник: Я сделал эту ошибку
Ответ 10
В некоторых случаях ваша директива выполняется дважды, когда вы просто не исправляете свою директиву так:
<my-directive>Some content<my-directive>
Это приведет к удвоению вашей директивы.
Также есть еще один случай, когда ваша директива выполняется дважды:
убедитесь, что вы не указали свою директиву в index.html
TWICE!
Ответ 11
Я почесал голову над этой проблемой с помощью AngularJS 1.4 rc build, а затем понял, что ни один из вышеприведенных ответов не применим, поскольку он был создан из новой библиотеки маршрутизаторов для Angular 1.4 и Angular 2 на момент написания этой статьи. Поэтому я оставляю примечание для всех, кто может использовать новую библиотеку маршрутов Angular.
В принципе, если html-страница содержит директиву ng-viewport
для загрузки частей вашего приложения, нажав на гиперссылку, указанную с помощью ng-link
, вы можете дважды загрузить целевой контроллер связанного компонента. Тонкая разница заключается в том, что, если браузер уже загрузил целевой контроллер, путем повторного нажатия одной и той же гиперссылки будет только один раз вызвать контроллер.
Пока не найдено жизнеспособного решения, хотя я считаю, что это поведение согласуется с наблюдением, поднятым shaunxu, и, надеюсь, эта проблема будет быть решены в будущем сборке новой библиотеки маршрутов и вместе с выпуском AngularJS 1.4.
Ответ 12
В моем случае я нашел два представления, используя один и тот же контроллер.
$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'
}
}
});
Ответ 13
Проблема, с которой я сталкиваюсь, может быть тангенциальной, но, поскольку поисковая оптимизация привела меня к этому вопросу, это может быть уместно. Проблема вызывает у меня уродливую голову, когда я использую UI Router, но только когда я пытаюсь обновить страницу кнопкой обновления браузера. Приложение использует UI-маршрутизатор с родительским абстрактным состоянием, а затем дочерние элементы от родителя. В функции app run()
есть команда $state.go('...child-state...')
. В родительском состоянии используется resolve
, и сначала я думал, что, возможно, дочерний контроллер выполняет дважды.
Все в порядке, прежде чем URL-адрес будет содержать хэш.
www.someoldwebaddress.org
Затем, как только URL был изменен с помощью UI Router,
www.someoldwebaddress.org#/childstate
... а затем, когда я обновить страницу кнопкой обновления браузера, $stateChangeStart
срабатывает дважды, и каждый раз указывает на childstate
.
resolve
в родительском состоянии - это то, что срабатывает дважды.
Возможно, это кудря; несмотря на это, похоже, это устраняет проблему для меня: в области кода, где сначала вызывается $stateProvider
, first, чтобы проверить, есть ли window.location.hash - пустая строка. Если это так, все хорошо; если это не так, установите window.location.hash в пустую строку. Тогда кажется, что $state
пытается только один раз пойти куда-то, а не дважды.
Кроме того, если вы не хотите полагаться на приложение по умолчанию run
и state.go(...)
, вы можете попытаться захватить хеш-значение и использовать значение хэша для определения дочернего состояния, которое вы были непосредственно перед обновлением страницы, и добавьте условие в область вашего кода, где вы устанавливаете state.go(...)
.
Ответ 14
В моем случае это было из-за шаблона url, который я использовал
мой url был как /ui/project/: parameter1/: parameter2.
Мне не нужно параметрирование2 во всех случаях изменения состояния. В тех случаях, когда мне не нужен второй параметр, мой url был бы как /ui/project/: parameter1/. И поэтому всякий раз, когда у меня было изменение состояния, я дважды обновляю свой контроллер.
Решением было установить параметр2 как пустую строку и сделать изменение состояния.
Ответ 15
У меня была двойная инициализация по другой причине. Для некоторых маршрутных переходов в моем приложении я хотел принудительно прокрутить до верхней части страницы (например, в постраничных результатах поиска... нажатие следующей должно привести вас к началу страницы 2).
Я сделал это, добавив слушателя к $rootScope
$on
$viewContentLoaded
, который (на основе определенных условий) выполнен
$location.hash('top');
Неосторожно это приводило к переоценке моих маршрутов и повторному инициализации контроллеров.
Ответ 16
У меня была такая же проблема, и после того, как я попробовал все ответы, я наконец обнаружил, что у меня есть директива в моем представлении, связанная с одним и тем же контроллером.
APP.directive('MyDirective', function() {
return {
restrict: 'AE',
scope: {},
templateUrl: '../views/quiz.html',
controller: 'ShowClassController'
}
});
После удаления директивы контроллер перестает вызываться дважды. Теперь мой вопрос: как использовать эту директиву, связанную с областью контроллера без этой проблемы?
Ответ 17
Моя проблема заключалась в обновлении параметров поиска, таких как $location.search('param', key);
вы можете прочитать об этом здесь
контроллер получает вызов дважды из-за добавления параметров в URL
Ответ 18
Я только что решил мой, что было на самом деле довольно разочаровывающим. Его ионное гибридное приложение, я использовал ui-router v0.2.13. В моем случае есть epub reader (с использованием epub.js), который постоянно сообщал "не найденный документ", как только я перехожу к библиотеке книг и выбираю любую другую книгу. Когда я перезагрузился, книга браузера была отлично отрисована, но когда я выбрал другую книгу, снова возникла проблема.
Мое решение было очень простым. Я просто удалил reload:true
из $state.go("app.reader", { fileName: fn, reload: true });
в мой LibraryController
Ответ 19
В моем случае переименование контроллера на другое имя решило проблему.
Существовал конфликт имен контроллеров с модулем "angular -ui-tree": я переименовал мой контроллер из "CatalogerTreeController" в "TreeController", а затем этот контроллер запускается дважды на странице, где используется директива "ui-tree", поскольку в этой директиве используется контроллер с именем "TreeController".
Ответ 20
Я понял, что мой вызов вызывает дважды, потому что я дважды вызывал метод из моего html.
`<form class="form-horizontal" name="x" ng-submit="findX() novalidate >
<input type="text"....>
<input type="text"....>
<input type="text"....>
<button type="submit" class="btn btn-sm btn-primary" ng-click="findX()"
</form>`
Выделенный раздел вызывает вызов findX() дважды. Надеюсь, это поможет кому-то.