javascript - Posiblemente rechazo no manejado en Angular 1.6




angularjs angular-promise (6)

Tengo un código con AngularJS:

service.doSomething()
  .then(function(result) {
      //do something with the result
  });

En AngularJS 1.5.9 cuando tengo un error en la sección .then() como:

service.doSomething()
  .then(function(result) {
      var x = null;
      var y = x.y;
      //do something with the result
  });

Me sale un mensaje de error claro:

TypeError: No se puede leer la propiedad 'y' de null

Pero en la versión 1.6 con el mismo código obtengo un error diferente:

Posiblemente rechazo no manejado: {} indefinido

Sé que esto está relacionado con este cambio , y la única solución es bastante simple al agregar el bloque .catch() :

service.doSomething()
  .then(function(result) {
      var x = null;
      var y = x.y;
      //do something with the result
  })
  .catch(console.error);

Ahora nuevamente tengo lo que quiero:

TypeError: No se puede leer la propiedad 'y' de null

Pero, ¿cómo obtener el mismo resultado (error más detallado) para toda la aplicación sin agregar el bloque .catch() en cada lugar?

Probé la solución sugerida para deshabilitar esto agregando:

$qProvider.errorOnUnhandledRejections(false);

Pero con esto, la situación es aún peor: ¡no tengo NADA en la consola! El error se traga en alguna parte y no se registra en absoluto. No estoy seguro de que sea un problema con AngularJS 1.6 o con mi configuración.

¿Tiene alguna idea de cómo "restaurar" el comportamiento de registro de la versión 1.5.9?

EDITAR:

Agregando un controlador de errores personalizado:

.factory('$exceptionHandler', function($log) {
  return function(exception, cause) {
    $log.warn(exception, cause);
  };
})

No ayuda en absoluto. En el controlador de errores ya recibo el error "envuelto".


Esta información me ayudó a rastrear qué (en mi caso) estaba creando la promesa y no agregar un controlador de errores. Lo encontré enterrado en la discusión del número 2889 "Posiblemente rechazo no manejado con Angular 1.5.9" .

Lo esencial, es, parche $q para almacenar en caché un seguimiento de la pila al crear promesas, de manera que se pueda recuperar cuando se desencadena el error.

Para hacerlo, inserte este código para decorar $q algún lugar cerca de la parte superior de su aplicación angular:

// Decorate the $q service when app starts
app.decorator('$q', ["$delegate", function($delegate) {
  // Create a new promise object
  var promise = $delegate.when();

  // Access the `Promise` prototype (nonstandard, but works in Chrome)
  var proto = promise.__proto__;

  // Define a setter for `$$state` that creates a stacktrace 
  // (string) and assigns it as a property of the internal `$$state` object.
  Object.defineProperty(proto, '$$state', {
    enumerable: true,
    set: function(val) {
      val.stack = new Error().stack;
      this._$$state = val;
    },
    get: function() {
      return this._$$state;
    }
  });

  return $delegate;
}]);

Luego busque en el código angular el mensaje "posible rechazo no manejado" y coloque un punto de interrupción en esa línea. Cuando se alcance el punto de interrupción, imprima el valor de toCheck.stack en la consola, y verá algo como esto:

>> toCheck.stack
"[email protected]://localhost:8000/js/dual-site.js:18:19
[email protected]://localhost:8000/js/angular.js:17008:22
[email protected]://localhost:8000/js/angular.js:17016:20
[email protected]://localhost:8000/js/angular.js:17026:14
[email protected]://localhost:8000/js/angular-state-machine.js:436:24
StateMachine/[email protected]://localhost:8000/js/angular-state-machine.js:235:16

El código ofensivo es el cuadro que llama a las funciones catch / then de angular.



La primera opción es simplemente ocultar un error con deshabilitar la errorOnUnhandledRejections de errorOnUnhandledRejections en $ qConfiguración del proveedor como se sugiere a Cengkuru Michael :

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

PERO esto solo apagará el registro. El error en sí permanecerá

La mejor solución en este caso será: manejar un rechazo con el método .catch() :

service.doSomething()
    .then(function (response) {})
    .catch(function (err) {});

Enlaces útiles:


Obtuve el mismo error de rechazo no manejado cuando una promesa rechazada no es manejada por angi-ui-router (ui-sref) usando ver1.6.1 angular. Esta función está habilitada de manera predeterminada.

Para cualquier persona que quiera una solución alternativa (aunque no se recomienda), puede silenciar globalmente los rechazos de promesa no manejados como este:

app.config(['$qProvider', function ($qProvider) { $qProvider.errorOnUnhandledRejections(false); }]);


Solucioné el mismo problema con la versión 1.6.1 al actualizar angular-ui-router a 0.3.2.


Tengo el problema incluso con la versión 1.6.1 en mi httpErrorInterceptor, por ejemplo, si mi API devuelve 404 tengo que intentar otra solicitud con otros datos ... así que en este caso solo rechazo la solicitud y arrojo el rechazo no manejado. error...

¡Instalo 1.5.9 y ahora no hay más errores!





angularjs-1.6