AngularJS: Prevent błąd $ digest już w toku podczas wywołania $ scope.$apply()

Znajduję, że muszę aktualizować moją stronę do mojego zakresu ręcznie coraz bardziej od budowania aplikacji w angular.

Jedynym sposobem, jaki znam, aby to zrobić, jest wywołanie $apply() z zakresu moich kontrolerów i dyrektyw. Problem z tym polega na tym, że Ciągle wyrzuca błąd do konsoli, który brzmi:

Error: $digest już w trakcie

Czy ktoś wie, jak uniknąć tego błędu lub osiągnąć to samo, ale w inny sposób?

Author: Ricky Dam, 2012-10-04

25 answers

Nie używaj tego wzorca - spowoduje to więcej błędów niż rozwiązuje. Nawet jeśli myślisz, że to coś naprawiło, to tak nie jest.]}

Możesz sprawdzić, czy $digest jest już w toku, sprawdzając $scope.$$phase.

if(!$scope.$$phase) {
  //$digest or $apply
}

$scope.$$phase zwróci "$digest" lub "$apply", Jeśli $digest lub $apply jest w toku. Myślę, że różnica między tymi stanami jest taka, że $digest przetworzy zegarki bieżącego zakresu i jego dzieci, a $apply przetworzy obserwatorów ze wszystkich lunet.

Do punktu @ dnc253, jeśli często dzwonisz $digest lub $apply, możesz robić to źle. Generalnie uważam, że muszę przetrawić, gdy muszę zaktualizować stan lunety w wyniku zdarzenia DOM wypalającego się poza zasięgiem kąta. Na przykład, gdy modal bootstrap Twittera staje się Ukryty. Czasami Zdarzenie DOM jest wywołane, gdy $digest jest w toku, czasami nie. Dlatego użyłem tego czeku.

Chciałbym poznać lepszy sposób, jeśli ktoś zna jeden.


From comments: by @ anddoutoi

Kanciaste.js anty Patterns

  1. nie rób if (!$scope.$$phase) $scope.$apply(), oznacza to, że Twój $scope.$apply() nie jest wystarczająco wysoki w stosie połączeń.
 638
Author: Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-01 16:49:17

Z niedawnej dyskusji z Angular guys na ten temat: ze względów przyszłościowych nie należy używać $$phase

Po naciśnięciu na "właściwy" sposób, aby to zrobić, odpowiedź brzmi obecnie

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})

Ostatnio natknąłem się na to, pisząc angular services, aby owijać interfejsy API facebook, google i twitter, które w różnym stopniu mają połączenia zwrotne.

Oto przykład z serwisu. (Ze względu na zwięzłość, reszta służby-że ustawianie zmiennych, wstrzykiwanie $timeout itp. -- zostało przerwane.)
window.gapi.client.load('oauth2', 'v2', function() {
    var request = window.gapi.client.oauth2.userinfo.get();
    request.execute(function(response) {
        // This happens outside of angular land, so wrap it in a timeout 
        // with an implied apply and blammo, we're in action.
        $timeout(function() {
            if(typeof(response['error']) !== 'undefined'){
                // If the google api sent us an error, reject the promise.
                deferred.reject(response);
            }else{
                // Resolve the promise with the whole response if ok.
                deferred.resolve(response);
            }
        });
    });
});

Zwróć uwagę, że argument delay dla $timeout jest opcjonalny i będzie domyślnie ustawiony na 0, jeśli zostanie wyłączony ($timeout wywoła $browser.defer który domyślnie wynosi 0, jeśli opóźnienie nie jest ustawione )

Trochę nieintuicyjne, ale to jest odpowiedź od facetów piszących Angular, więc jest wystarczająco dobre dla mnie!

 636
Author: betaorbust,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-25 04:06:19

Cykl digest jest wywołaniem synchronicznym. Dopóki nie zostanie to wykonane, Kontrola nie przejdzie do pętli zdarzeń przeglądarki. Jest kilka sposobów, aby sobie z tym poradzić. Najprostszym sposobem na poradzenie sobie z tym jest użycie wbudowanego $timeout, a drugim sposobem jest użycie podkreślenia lub lodash (i powinieneś), wywołanie następującej opcji:

$timeout(function(){
    //any code in here will automatically have an apply run afterwards
});

Lub jeśli masz podkreślenie:

_.defer(function(){$scope.$apply();});

Wypróbowaliśmy kilka obejść i nienawidziliśmy wstrzykiwania $rootScope do wszystkich naszych kontrolerów, dyrektyw, a nawet kilka fabryk. Więc, $timeout i _.defer były do tej pory naszym ulubionym. Metody te z powodzeniem powiedzieć angular poczekać do następnej pętli animacji, co zagwarantuje, że bieżący zakres.$apply jest skończone.

 314
Author: frosty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-09 22:29:02

Wiele odpowiedzi zawiera dobre rady, ale może również prowadzić do zamieszania. Po prostu użycie $timeout jest nie najlepszym ani właściwym rozwiązaniem. Pamiętaj również, aby przeczytać, że jeśli obawiasz się wydajności lub skalowalności.

Things you should know

  • $$phase jest prywatna dla RAM i są ku temu dobre powody.

  • $timeout(callback) będzie czekać do bieżącego cyklu digest (jeśli w ogóle) jest zrobione, następnie wykonać callback, a następnie uruchomić na koniec pełny $apply.

  • $timeout(callback, delay, false) zrobi to samo (z opcjonalnym opóźnieniem przed wykonaniem wywołania zwrotnego), ale nie uruchomi $apply (trzeciego argumentu), który zapisuje występy, jeśli nie zmodyfikowałeś swojego modelu kątowego ($scope).

  • $scope.$apply(callback) wywołuje między innymi $rootScope.$digest, co oznacza, że zmieni główny zakres aplikacji i wszystkich jej dzieci, nawet jeśli znajdujesz się w odosobnionym zakresie.

  • $scope.$digest() wystarczy zsynchronizować swój model z widok, ale nie przetrawi swojego macierzystego zakresu, co może zaoszczędzić wiele wydajności podczas pracy nad izolowaną częścią twojego HTML z izolowanym zakresem (głównie z dyrektywy). $digest nie przyjmuje wywołania zwrotnego: wykonujesz kod, a następnie trawisz.

  • $scope.$evalAsync(callback) został wprowadzony w angularjs 1.2 i prawdopodobnie rozwiąże większość twoich problemów. Zapoznaj się z ostatnim akapitem, aby dowiedzieć się więcej na ten temat.

  • Jeśli otrzymasz $digest already in progress error, to twoja Architektura błąd: albo nie musisz redigestować swojego zakresu, albo nie powinieneś być odpowiedzialny za to (patrz poniżej).

Jak ułożyć swój kod

Kiedy dostajesz ten błąd, próbujesz strawić swój zakres, gdy jest on już w toku: ponieważ nie znasz stanu swojego zakresu w tym momencie, nie jesteś odpowiedzialny za radzenie sobie z jego trawieniem.

function editModel() {
  $scope.someVar = someVal;
  /* Do not apply your scope here since we don't know if that
     function is called synchronously from Angular or from an
     asynchronous code */
}

// Processed by Angular, for instance called by a ng-click directive
$scope.applyModelSynchronously = function() {
  // No need to digest
  editModel();
}

// Any kind of asynchronous code, for instance a server request
callServer(function() {
  /* That code is not watched nor digested by Angular, thus we
     can safely $apply it */
  $scope.$apply(editModel);
});

I jeśli wiesz, co robisz i pracujesz nad odizolowaną małą dyrektywą, podczas gdy część z dużej aplikacji kątowej, możesz preferować $digest zamiast $apply, aby zapisać występy.

Aktualizacja od Angularjs 1.2

Nowa, potężna metoda została dodana do dowolnego $scope: $evalAsync. Zasadniczo, będzie wykonywać swoje wywołanie zwrotne w bieżącym cyklu fermentacji, jeśli jeden występuje, w przeciwnym razie nowy cykl fermentacji rozpocznie wykonywanie wywołania zwrotnego.

To nadal nie jest tak dobre jak $scope.$digest jeśli naprawdę wiesz, że musisz tylko zsynchronizować izolowaną część swojego HTML (ponieważ nowa $apply zostanie uruchomiona, jeśli żadna nie jest w toku), ale jest to najlepsze rozwiązanie, gdy wykonujesz funkcję, która nie możesz wiedzieć, czy będzie wykonywana synchronicznie, czy nie , na przykład po pobraniu zasobu potencjalnie buforowanego: czasami wymaga to asynchronicznego wywołania do serwera, w przeciwnym razie zasób zostanie pobrany lokalnie synchronicznie.

W tych przypadkach i wszystkich innych, w których miałeś !$scope.$$phase, pamiętaj, aby użyć $scope.$evalAsync( callback )

 258
Author: floribon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-21 19:43:53

Poręczna metoda małego pomocnika, aby utrzymać ten proces w suchości:

function safeApply(scope, fn) {
    (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}
 86
Author: lambinator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-14 18:14:15

Zobacz http://docs.angularjs.org/error/$rootScope: inprog

Problem pojawia się, gdy masz wywołanie $apply, które czasami jest uruchamiane asynchronicznie poza kodem kątowym (gdy należy użyć $apply), a czasami synchronicznie wewnątrz kodu kątowego (co powoduje błąd $digest already in progress).

Może się to zdarzyć na przykład, gdy masz bibliotekę, która asynchronicznie pobiera elementy z serwera i je buforuje. Przy pierwszym zamówieniu przedmiotu zostanie on pobrany asynchronicznie, aby nie blokować wykonywania kodu. Za drugim razem jednak element jest już w pamięci podręcznej, więc można go pobrać synchronicznie.

Aby zapobiec temu błędowi, należy upewnić się, że kod wywołujący $apply jest uruchamiany asynchronicznie. Można to zrobić uruchamiając kod wewnątrz wywołania $timeout z opóźnieniem ustawionym na 0 (co jest domyślne). Jednak wywołanie kodu wewnątrz $timeout usuwa konieczność wywołania $apply, ponieważ $timeout wywoła kolejny cykl $digest na własne, które z kolei wykonają wszystkie niezbędne aktualizacje itp.

Rozwiązanie

W skrócie, zamiast tego:

... your controller code...

$http.get('some/url', function(data){
    $scope.$apply(function(){
        $scope.mydate = data.mydata;
    });
});

... more of your controller code...

Zrób to:

... your controller code...

$http.get('some/url', function(data){
    $timeout(function(){
        $scope.mydate = data.mydata;
    });
});

... more of your controller code...

Tylko połączenie $apply Gdy znasz uruchomiony kod, zawsze będzie uruchamiane poza kodem kątowym(np. połączenie do $apply nastąpi wewnątrz wywołania zwrotnego, które jest wywoływane kodem poza kodem kątowym).

Chyba, że ktoś jest świadomy jakiejś niekorzystnej sytuacji w używaniu $timeout przez $apply, I nie rozumiem, dlaczego nie można zawsze używać $timeout (z zerowym opóźnieniem) zamiast $apply, ponieważ zrobi to mniej więcej to samo.

 32
Author: Trevor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-17 23:37:16

Miałem ten sam problem ze skryptami innych firm jak na przykład CodeMirror i Krpano, i nawet Korzystanie z wymienionych tutaj metod safeApply nie rozwiązało dla mnie błędu.

Ale co rozwiązało to jest użycie usługi $ timeout (nie zapomnij najpierw go wstrzyknąć).

Tak więc coś w rodzaju:

$timeout(function() {
  // run my code safely here
})

A jeśli wewnątrz kodu używasz

To

Może dlatego, że jest wewnątrz kontrolera dyrektywy fabrycznej lub po prostu potrzebuje jakiegoś Wiązanie, wtedy zrobiłbyś coś takiego:

.factory('myClass', [
  '$timeout',
  function($timeout) {

    var myClass = function() {};

    myClass.prototype.surprise = function() {
      // Do something suprising! :D
    };

    myClass.prototype.beAmazing = function() {
      // Here 'this' referes to the current instance of myClass

      $timeout(angular.bind(this, function() {
          // Run my code safely here and this is not undefined but
          // the same as outside of this anonymous function
          this.surprise();
       }));
    }

    return new myClass();

  }]
)
 31
Author: Ciul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-13 07:52:34

Kiedy pojawi się ten błąd, oznacza to, że jest on już w trakcie aktualizacji widoku. Naprawdę nie powinieneś dzwonić $apply() w swoim kontrolerze. Jeśli widok nie aktualizuje się zgodnie z oczekiwaniami, a następnie pojawia się ten błąd po wywołaniu $apply(), najprawdopodobniej oznacza to, że nie aktualizujesz poprawnie modelu. Jeśli napiszesz jakieś szczegóły, możemy znaleźć główny problem.

 28
Author: dnc253,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-04 14:41:41

Najkrótszą formą bezpiecznego $apply jest:

$timeout(angular.noop)
 14
Author: Warlock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 05:04:44

Możesz również użyć evalAsync. Będzie działać jakiś czas po zakończeniu digest!

scope.evalAsync(function(scope){
    //use the scope...
});
 11
Author: CMCDragonkai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-19 01:48:42

Czasami nadal pojawią się błędy, jeśli użyjesz tego sposobu ( https://stackoverflow.com/a/12859093/801426).

Spróbuj tego:

if(! $rootScope.$root.$$phase) {
...
 9
Author: bullgare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:39

Po pierwsze, nie naprawiaj tego w ten sposób

if ( ! $scope.$$phase) { 
  $scope.$apply(); 
}

To nie ma sensu, ponieważ $phase jest tylko flagą logiczną dla cyklu $ digest, więc twoja $apply () czasami nie będzie działać. I pamiętaj, że to zła praktyka.

Zamiast tego użyj $timeout

    $timeout(function(){ 
  // Any code in here will automatically have an $scope.apply() run afterwards 
$scope.myvar = newValue; 
  // And it just works! 
});

Jeśli używasz podkreślenia lub lodash, możesz użyć defer():

_.defer(function(){ 
  $scope.$apply(); 
});
 7
Author: M Sagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 09:37:27

Powinieneś użyć $evalAsync lub $timeout zgodnie z kontekstem.

To jest link z dobrym wyjasnieniem:

Http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm

 5
Author: Luc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 05:04:58

Radzę ci użyć niestandardowego zdarzenia, zamiast wywoływać cykl trawienia.

Doszedłem do wniosku, że nadawanie niestandardowych wydarzeń i rejestrowanie słuchaczy tego wydarzenia jest dobrym rozwiązaniem dla wyzwalania akcji, którą chcesz wystąpić, niezależnie od tego, czy jesteś w cyklu digest.

Tworząc zdarzenie niestandardowe, jesteś również bardziej efektywny z kodem, ponieważ tylko wyzwalasz słuchaczy subskrybowanych do tego zdarzenia i nie wyzwalasz wszystkich zegarków związanych z zakresem tak jak ty, gdybyście powołali się na zakres.$apply.

$scope.$on('customEventName', function (optionalCustomEventArguments) {
   //TODO: Respond to event
});


$scope.$broadcast('customEventName', optionalCustomEventArguments);
 4
Author: nelsonomuto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-02 15:26:46

Yearofmoo wykonał świetną robotę przy tworzeniu funkcji $safeApply wielokrotnego użytku dla nas:

Https://github.com/yearofmoo/AngularJS-Scope.SafeApply

Użycie:

//use by itself
$scope.$safeApply();

//tell it which scope to update
$scope.$safeApply($scope);
$scope.$safeApply($anotherScope);

//pass in an update function that gets called when the digest is going on...
$scope.$safeApply(function() {

});

//pass in both a scope and a function
$scope.$safeApply($anotherScope,function() {

});

//call it on the rootScope
$rootScope.$safeApply();
$rootScope.$safeApply($rootScope);
$rootScope.$safeApply($scope);
$rootScope.$safeApply($scope, fn);
$rootScope.$safeApply(fn);
 3
Author: RNobel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 05:05:35

Udało mi się rozwiązać ten problem wywołując $eval zamiast $apply w miejscach, gdzie Wiem, że funkcja $digest będzie działać.

Zgodnie z docs, $apply zasadniczo robi to:

function $apply(expr) {
  try {
    return $eval(expr);
  } catch (e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

W moim przypadku, ng-click zmienia zmienną w zakresie, a $watch na tej zmiennej zmienia inne zmienne, które muszą być $applied. Ten ostatni krok powoduje błąd "trawienie już w toku".

Poprzez zastąpienie $apply $eval wewnątrz zegarka wyrażenie zmienne zakresu są aktualizowane zgodnie z oczekiwaniami.

Dlatego wydaje się , że jeśli digest i tak będzie działał z powodu jakiejś innej zmiany w Angular, $eval'ING jest wszystkim, co musisz zrobić.

 2
Author: teleclimber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 19:08:00

Użyj $scope.$$phase || $scope.$apply(); zamiast

 2
Author: Visakh B Sujathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 05:05:14

Spróbuj użyć

$scope.applyAsync(function() {
    // your code
});

Zamiast

if(!$scope.$$phase) {
  //$digest or $apply
}

$applyAsync zaplanuje wywołanie $apply, aby miało miejsce w późniejszym czasie. To może być używane do kolejkowania wielu wyrażeń, które muszą być ocenione w tym samym fragmencie.

Uwaga: w obrębie $digest, $applyAsync () będzie spłukiwana tylko wtedy, gdy bieżącym zakresem jest $rootScope. Oznacza to, że wywołanie $digest w zakresie podrzędnym nie spowoduje domyślnie spłukania kolejki $applyAsync ().

Exmaple:

  $scope.$applyAsync(function () {
                if (!authService.authenticated) {
                    return;
                }

                if (vm.file !== null) {
                    loadService.setState(SignWizardStates.SIGN);
                } else {
                    loadService.setState(SignWizardStates.UPLOAD_FILE);
                }
            });

Bibliografia:

1.zakres.$applyAsync () vs.Scope.$evalAsync () in AngularJS 1.3

  1. AngularJs Docs
 2
Author: Eduardo Eljaiek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 14:34:17

Rozumiejąc, że dokumenty kątowe wywołują sprawdzanie $$phase an anty-pattern , starałem się, aby $timeout i _.defer działały.

Metody timeout i deferred tworzą flash nieparowanej {{myVar}} zawartości w dom jak FOUT. Dla mnie było to nie do przyjęcia. Pozostawia mi wiele do powiedzenia dogmatycznie, że coś jest hack, a nie mają odpowiedniej alternatywy.

Jedyną rzeczą, która działa za każdym razem jest:

if(scope.$$phase !== '$digest'){ scope.$digest() }.

I don ' t zrozum niebezpieczeństwo tej metody, lub dlaczego jest ona opisana jako hack przez ludzi w komentarzach i zespół angular. Polecenie wydaje się precyzyjne i łatwe do odczytania:

"zrób digest, chyba że już się dzieje"

W CoffeeScript jest jeszcze ładniejsza:

scope.$digest() unless scope.$$phase is '$digest'

W czym problem? Czy istnieje alternatywa, która nie stworzy Fouta? $ safeApply wygląda dobrze, ale używa metody kontroli $$phase.
 1
Author: SimplGy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-03 22:43:27

To jest moja usługa utils:

angular.module('myApp', []).service('Utils', function Utils($timeout) {
    var Super = this;

    this.doWhenReady = function(scope, callback, args) {
        if(!scope.$$phase) {
            if (args instanceof Array)
                callback.apply(scope, Array.prototype.slice.call(args))
            else
                callback();
        }
        else {
            $timeout(function() {
                Super.doWhenReady(scope, callback, args);
            }, 250);
        }
    };
});

A to jest przykład jego użycia:

angular.module('myApp').controller('MyCtrl', function ($scope, Utils) {
    $scope.foo = function() {
        // some code here . . .
    };

    Utils.doWhenReady($scope, $scope.foo);

    $scope.fooWithParams = function(p1, p2) {
        // some code here . . .
    };

    Utils.doWhenReady($scope, $scope.fooWithParams, ['value1', 'value2']);
};
 1
Author: ranbuch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-24 05:59:15

Używam tej metody i wydaje się, że działa idealnie. Po prostu czeka na czas zakończenia cyklu, a następnie uruchamia apply(). Po prostu wywołaj funkcję apply(<your scope>) z dowolnego miejsca.

function apply(scope) {
  if (!scope.$$phase && !scope.$root.$$phase) {
    scope.$apply();
    console.log("Scope Apply Done !!");
  } 
  else {
    console.log("Scheduling Apply after 200ms digest cycle already in progress");
    setTimeout(function() {
        apply(scope)
    }, 200);
  }
}
 1
Author: Ashu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-14 08:10:46

Podobne do odpowiedzi powyżej, ale to działa wiernie dla mnie... w serwisie dodaj:

    //sometimes you need to refresh scope, use this to prevent conflict
    this.applyAsNeeded = function (scope) {
        if (!scope.$$phase) {
            scope.$apply();
        }
    };
 0
Author: Shawn Dotey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-12 20:39:08

Możesz użyć

$timeout

Aby zapobiec błędowi.

 $timeout(function () {
                        var scope = angular.element($("#myController")).scope();
                        scope.myMethod();
                        scope.$scope();
                    },1);
 0
Author: Satish Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-15 10:54:26

Znalazłem to: https://coderwall.com/p/ngisma Gdzie Nathan Walker (na dole strony) sugeruje dekorator w $rootScope, aby utworzyć func 'safeApply', kod:

yourAwesomeModule.config([
  '$provide', function($provide) {
    return $provide.decorator('$rootScope', [
      '$delegate', function($delegate) {
        $delegate.safeApply = function(fn) {
          var phase = $delegate.$$phase;
          if (phase === "$apply" || phase === "$digest") {
            if (fn && typeof fn === 'function') {
              fn();
            }
          } else {
            $delegate.$apply(fn);
          }
        };
        return $delegate;
      }
    ]);
  }
]);
 -3
Author: Warren Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-11 20:00:09

To rozwiąże twój problem:

if(!$scope.$$phase) {
  //TODO
}
 -7
Author: eebbesen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-12 03:41:45