I'm using AngularJS version of 1.7.2 and got an exception with this message
Cannot read property 'dataItem' of undefined
and it is not throwing into console / customExceptionHandling Service Because code in AngularJS is below:
catch (e) {
rejectPromise(promise, e);
// This error is explicitly marked for being passed to the $exceptionHandler
if (e && e.$$passToExceptionHandler === true) {
exceptionHandler(e);
}
}
that $$passToExceptionHandler is not present in e object and exceptionHandler function is not calling.
Can anyone please explain to me why this is happening?
You might have disabled reporting unhandled rejected promises with this line:
qProvider.errorOnUnhandledRejections(false);
But generally more information about the error source are required to give you better answer.
Maybe this will work, set $$passToExceptionHandler to all "Error" instance like:
Error.prototype.$$passToExceptionHandler = true
Related
This question already has answers here:
Is it not possible to stringify an Error using JSON.stringify?
(14 answers)
'Uncaught Error: DATA_CLONE_ERR: DOM Exception 25' thrown by web worker
(2 answers)
Closed 3 years ago.
Using AngularJs v1.5.7, I'm having quite some trouble trying to log the exception.
The issue seem to be with the type of the exception.
This object is somehow not a normal object with properties.
Here is a code sample with what I have attempted so far and the result for each attempts.
MyApp.config(['$provide', function ($provide)
{
$provide.decorator('$exceptionHandler', ['$delegate', 'logsService', function ($delegate, logsService)
{
return function (exception, cause)
{
$delegate(exception, cause);
try
{
//Attempt #1 : throw because exception isn't an object.
logsService.addLog(exception);
//Attempt #2 : Log the hardcoded object with both properties
logsService.addLog({a:'Some test', b:'Ok'});
//Attempt #3 : log an empty object because exception has no property
var log = {};
for (var property in exception)
{
if (object.hasOwnProperty(property))
{
log[property] = exception[property];
}
}
logsService.addLog(log);
//Attempt #4 : Log the message, but doesn't log all possible properties that exception could have.
logsService.addLog({ message: exception.message});
}
catch (ignore) { }
};
}]);
}]);
N.B : I can't change the logsService.
So far, I didn't find anything about this on google.
Why does exception has no properties and how to work around this limitation?
Edit :
I think I've pinpoint a little more the issue. The exception object is probably not clean and have functions or others things that can't be cloned. This give the following error in the log service.
DataCloneError: Failed to execute 'put' on 'IDBObjectStore'`
Source
Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.
//Attempt #5 : log an empty object because exception has no property.
var cleanedException = JSON.parse(angular.toJson(exception));
logsService.addLog(cleanedException);
Is is what the exception show when inspecting it in the watch.
To copy an Error object to a plain JavaScript object:
e = new Error("Example");
plain = { message: e.message, stack: e.stack };
console.log(plain);
Then it can be cloned for a Web Worker.
This issue is caused because error can't be cloned as stated here which is quite suttle.
Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.
So others have ran into related issue Is it not possible to stringify an Error using JSON.stringify? and they found a work around using Object.getOwnPropertyNames. Object.getOwnPropertyNames has been the way to go for me because all possible properties will be logged.
//Attempt #6: Log all properties
var cleanedException = JSON.parse(JSON.stringify(exception, Object.getOwnPropertyNames(exception)));
logsService.addLog(cleanedException);
I have recently updated my application from Angular 1.5 to 1.6.3 and started getting Jasmine unit test failures (with PhantomJS) around promise based code I have written:
Possibly unhandled rejection: undefined thrown
Reading around I see that the accepted solution is to chain .then() with .catch() blocks to handle the rejections gracefully.
I have done this for one of my source files that I am testing to prove this gets past the error which it does.
However, it has now uncovered a further issue where an expectation I am testing when a promise rejection is called in my code is no longer passing.
This is the function I am trying to test (after adding the required catch blocks)
public deleteSomething = (thing) => {
return this.UserMessages.buildConfirmDialog().then(() => {
this.someService.remove(thing)
.then(() => {
this.UserMessages.showToast('Something deleted');
})
.catch((error) => {
//handle error
});
})
.catch((error) => {
//handle error
});
}
And here is the test:
var thing = {foo: 'bar'},
deferredRemove,
deferredConfirm,
//Mock service below injected into controller later on before test are run
UserMessages = {
buildConfirmDialog: jasmine.createSpy('buildConfirmDialog').and.callFake(function() {
deferredConfirm = $q.defer();
return deferredConfirm.promise.catch(angular.noop);
})
};
//Inject and controller setup here...
describe('When deleting something', function() {
beforeEach(function() {
deferredRemove = $q.defer();
spyOn(someService, 'remove').and.returnValue(deferredRemove.promise.catch(angular.noop));
});
describe('and the user confirms the deletion', function() {
beforeEach(function() {
ctrl.deleteSomething(thing);
deferredConfirm.resolve();
deferredRemove.resolve();
$rootScope.$apply();
});
it('should call remove on someService', function() {
console.log('someService.remove.calls = ' + someService.remove.calls.count());
expect(someService.remove).toHaveBeenCalled();
});
});
describe('and the user cancels the deletion', function() {
beforeEach(function() {
someService.remove.calls.reset();
vm.deleteSomething(thing);
deferredConfirm.reject({});
$rootScope.$apply();
});
it('should not call remove on someService', function() {
console.log('someService.remove.calls = ' + someService.remove.calls.count());
expect(someService.remove.calls.count()).toEqual(0);
});
});
});
I didnt have the .catch(angular.noop) parts in prior to upgrading to 1.6.3 and came across some posts suggesting to do this in order to make the tests happy, which certainly helped for me in getting past the unhandled rejection error in my test run.
The problem I am now facing is that for the reject test spec, there should be no call made to a remove function in my service, and so the number of calls should be zero, but it keeps coming out as 1. I added the line to reset the calls in my test to be sure it wasnt the previous test contributing (I know calls are meant to be reset between tests).
This test was running just fine when I was on 1.5, so this has to be something with the way my code\test is written not playing nicely with changes in 1.6.x
Can someone shed some light on what may be going on here please?
Thanks
I didnt have the .catch(angular.noop) parts in prior to upgrading to 1.6.3 and came across some posts suggesting to do this in order to make the tests happy, which certainly helped for me in getting past the unhandled rejection error in my test run.
Adding .catch(angular.noop) will certainly handle the unhandled rejection.
It converts the rejected promise to a fulfilled promise!!
Your test is correctly failing because you broke your code.
For more information, see Catch method not working with $http get request
Changes to $q for AngularJS V1.6
report promises with non rejection callback
Rejected promises that do not have a callback to handle the rejection report
this to $exceptionHandler so they can be logged to the console.
BREAKING CHANGE
Unhandled rejected promises will be logged to $exceptionHandler.
Tests that depend on specific order or number of messages in $exceptionHandler
will need to handle rejected promises report.
treat thrown errors as regular rejections
Previously, errors thrown in a promise's onFulfilled or onRejected handlers were treated in a
slightly different manner than regular rejections:
They were passed to the $exceptionHandler() (in addition to being converted to rejections).
The reasoning for this behavior was that an uncaught error is different than a regular rejection, as
it can be caused by a programming error, for example. In practice, this turned out to be confusing
or undesirable for users, since neither native promises nor any other popular promise library
distinguishes thrown errors from regular rejections.
(Note: While this behavior does not go against the Promises/A+ spec, it is not prescribed either.)
This commit removes the distinction, by skipping the call to $exceptionHandler(), thus treating
thrown errors as regular rejections.
Note:
Unless explicitly turned off, possibly unhandled rejections will still be caught and passed to the
$exceptionHandler(), so errors thrown due to programming errors and not otherwise handled (with a
subsequent onRejected handler) will not go unnoticed.
For more information, see AngularJS Developer Guide - Migrating from V1.5 to V1.6
disable Possibly Unhandled Rejection by this config and test again.
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
Im working on a project that involves AngularJS and I am running into an error cant seem to figure out. Needless to say, I am a newbie on this hopefully you guys could help me figure this out cause I 've spent quite sometime on this issue.
here is my code
WatchboxCtrl.js
https://gist.github.com/anonymous/0c68fbd87574d61377b54981a09f66e5
and this is where the error occurs
FleetMapCtrl.js
https://gist.github.com/anonymous/9df7bc7c54a09c91dd60cd009ba9ff91
Ultimately, what i want to do is, having the app shows multiple alerts and if i click on one of the alert, the app should automatically zoom in onto the unit that the alert is originated. Previously, I have the "id" as string and it was working fine;however, I later on changed the "id" to integer and the zoom functionality no longer working. The console in gives me this error every time i click on the alert :
angular.js:11655 TypeError: Cannot read property 'toString' of undefined
at flyTo (FleetMapCtrl.js:320)
at Object.fn (FleetMapCtrl.js:287)
at Scope.$digest (angular.js:14308)
at Scope.$apply (angular.js:14571)
at HTMLButtonElement.<anonymous> (angular.js:21571)
at HTMLButtonElement.dispatch (jquery-2.0.3.min.js:5)
at HTMLButtonElement.y.handle (jquery-2.0.3.min.js:5)
It showing the error at line 320 in fleetmapCtrl.js but I cant figure out/understand why it's not working.
Please help. I searched everywhere in order to fix it but I cant seem to get it resolved. Im desperate. Thanks
As you said, the newval is no more a string and there is no zoomlevel in newVal.
When you are accessing newVal.zoomLevel it will give undefined only.
I think the below line is having issue. I coudn't see anywhere you are assigning zoomLevel to that object. Please excuse me if i missed out the same.
$scope.markers = getMarkers($scope.mapData[newVal.zoomLevel.toString()]);
You are not checking for undefined in your little method.
function isUndefinedOrNull(val) {
if (val === "" || val === null || val === "undefined") {
return true;
}
}
You are checking for the string "undefined" not undefined.
console.log(undefined==="undefined"); //false
So it should be without the quotes
function isUndefinedOrNull(val) {
return val === "" || val === null || val === undefined;
}
Now why is it undefined? You would need to track down where flyTo is being called and figure out why the watch is not returning the new value.
I did find a way to handle uncaught exceptions in angularjs by using predefined $exceptionHandler service. According to the doc, I'm delegating exceptions manually by using try {...} - catch(e). See below
try {
$scope.loadImage();
}catch (e){
console.log(e);
}
It is working absolutely fine
But I eager to know how could I handle uncaught exceptions in angular way ? Can anyone please share a working example ?
It is explained in the API.
angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
return function(exception, cause) {
exception.message += ' (caused by "' + cause + '")';
throw exception;
};
});
This example will override the normal action of
$exceptionHandler, to make angular exceptions fail hard when they
happen, instead of just logging to the console.
Note, that code executed in event-listeners (even those registered
using jqLite's on/bind methods) does not delegate exceptions to the
$exceptionHandler (unless executed during a digest). If you wish,
you can manually delegate exceptions, e.g. try { ... } catch(e) {
$exceptionHandler(e); }
Let say we have a simple entity level validator like this:
function entityIdIsValidFn(entity,context) {
if (entity.Id1)
return true;
if (entity.Id2)
return true;
return false;
}
var entityIdValidator = new breeze.Validator("entityIdValidator", entityIdIsValidFn, { messageTemplate: "Id1 or Id2 must be defined" });
var entityType = manager.metadataStore.getEntityType("Entity");
entityType.validators.push(entityIdValidator);
Now if I try to display validation error messages in a angularjs view like this:
<div ng-repeat="error in selectedEntity.entityAspect.getValidationErrors() " class="alert alert-danger">{{error.errorMessage}}</div>
I get a bunch of Error: 10 $digest() iterations reached. Aborting! errors.
If I have validators only attached to properties validation errors will display just fine but once I attach avalidator to an entity type I run into trouble. Anybody got an idea why this happens and consequently how to display validation error messages correctly?
Any help would be much appreciated.
While I did not get your error I had no problem reproducing one of my own. There is a Breeze bug in getValidationErrors (line 3839 of breeze.debug.js v.1.4.6) where it iterates over the error collection, testing the property name.
ve.property.name === propertyName
An entity-level validation error (ve) does not have a property and therefore the code fails with a null reference error while trying to access the undefined property.name.
A temporary workaround might be to patch this line with
ve.property && ve.property.name === propertyName
We've fixed it in GitHub. It will appear in the next (1.4.7) release. Thanks for reporting it.