angularjs - new - $ aplicar error en curso
broadcast angularjs (10)
Stack trace:
Error: $apply already in progress
at Error (<anonymous>)
at beginPhase (file:///android_asset/www/built.min.js:7:22740)
at Object.Scope.$apply (file:///android_asset/www/built.min.js:7:25967)
at navigator.geolocation.getCurrentPosition.that (file:///android_asset/www/built.min.js:13:8670)
at Object.geolocation.getCurrentPosition (file:///android_asset/www/plugins/org.apache.cordova.core.geolocation/www/geolocation.js:122:13)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8589)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8277)
at Object.getCurrentCity (file:///android_asset/www/built.min.js:13:8941)
at Object.$scope.locateDevice (file:///android_asset/www/built.min.js:13:10480)
at file:///android_asset/www/built.min.js:7:12292:7
se refiere a este código http://pastebin.com/B9V6yvFu
getCurrentPosition: cordovaReady(function (onSuccess, onError, options) {
navigator.geolocation.getCurrentPosition(function () {
var that = this,
args = arguments;
if (onSuccess) {
$rootScope.$apply(function () {
onSuccess.apply(that, args);
});
}
}, function () {
var that = this,
args = arguments;
if (onError) {
$rootScope.$apply(function () {
onError.apply(that, args);
});
}
}, {
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 18000000
});
})
Extraño, en mi LG4X funciona bien, sin embargo, en mi samsung s2 arroja el error anterior. ¿Alguna idea de lo que está mal?
En 1.3 angular, creo, agregaron una nueva función - $scope.$applyAsync()
. Esta función llama a aplicar más tarde; al menos unos 10 ms más tarde. No es perfecto, pero al menos elimina el molesto error.
https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope # $ applyAsync
En cualquier momento, solo puede haber una operación $digest
o $apply
en progreso. Esto es para evitar que errores muy difíciles de detectar ingresen a su aplicación. El seguimiento de la pila de este error le permite rastrear el origen de la ejecución actual de la llamada $apply
o $digest
, que provocó el error.
Más información: https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply
En mi caso uso $apply
con UI de calendario angular para vincular algún evento:
$scope.eventClick = function(event){
$scope.$apply( function() {
$location.path(''/event/'' + event.id);
});
};
Después de leer el documento del problema: https://docs.angularjs.org/error/ $ rootScope / inprog
La parte Inconsistent API (Sync / Async) es muy interesante:
Por ejemplo, imagina una biblioteca de terceros que tiene un método que recuperará datos para nosotros. Como puede estar haciendo una llamada asincrónica a un servidor, acepta una función de devolución de llamada, que se invocará cuando lleguen los datos.
Como el constructor MyController siempre se crea una instancia desde una llamada $ apply, nuestro controlador intenta ingresar un nuevo bloque $ apply desde uno.
Cambio el código a:
$scope.eventClick = function(event){
$timeout(function() {
$location.path(''/event/'' + event.id);
}, 0);
};
Funciona de maravilla !
Aquí hemos usado $ timeout para programar los cambios en el alcance en una pila de llamadas futura. Al proporcionar un período de tiempo de espera de 0ms, esto ocurrirá tan pronto como sea posible y $ timeout garantizará que el código se invoque en un único bloque $ apply.
Está recibiendo este error porque llama $apply
dentro de un ciclo de digestión existente.
La gran pregunta es: ¿por qué llamas $apply
? No deberías necesitar llamar $apply
menos que estés interactuando desde un evento no angular. La existencia de $apply
generalmente significa que estoy haciendo algo mal (a menos que, una vez más, la $ apply ocurra a partir de un evento no Angular).
Si $apply
realmente es apropiado aquí, considere usar un enfoque de "aplicación segura":
Llamo a $ scope. $ Aplicar de esta manera para ignorar llamada múltiple de una vez.
var callApplyTimeout = null;
function callApply(callback) {
if (!callback) callback = function () { };
if (callApplyTimeout) $timeout.cancel(callApplyTimeout);
callApplyTimeout = $timeout(function () {
callback();
$scope.$apply();
var d = new Date();
var m = d.getMilliseconds();
console.log(''$scope.$apply(); call '' + d.toString() + '' '' + m);
}, 300);
}
simplemente llame
callApply();
Puedes usar esta declaración:
if ($scope.$root.$$phase != ''$apply'' && $scope.$root.$$phase != ''$digest'') {
$scope.$apply();
}
Sé que es una pregunta antigua, pero si realmente necesitas usar $ scope. $ ApplyAsync ();
Si se debe aplicar el alcance en algunos casos, puede establecer un tiempo de espera para que la $ apply se posponga hasta el próximo tick
setTimeout(function(){ scope.$apply(); });
o envuelva su código en $ timeout (function () {..}); porque automáticamente $ aplicará el alcance al final de la ejecución. Si necesita que su función se comporte sincrónicamente, yo haría la primera.
Simplemente use $evalAsync lugar de $apply
.
Solo resolvió este problema. Está documentado aquí .
$rootScope.$apply
dos veces en el mismo flujo. Todo lo que hice fue envolver el contenido de la función de servicio con un setTimeout(func, 1)
.