Why is this property swallowing errors? - ember.js

I have a property that depends on another property. There is an error in my code that happens when the other property is present. The error is being swallowed by something, probably Ember. This makes debugging the error very hard. I have tried setting Ember.onerror to a function that just logs the error, it makes no difference.
Why is Ember swallowing this error, how can I make it not?
Code:
App.DashboardController = Ember.Controller.extend({
leaderboard: function() {
console.log("calling leaderboard");
var ces = this.get("engagements");
if (ces) {
console.log("before");
throw new Error("bad thing");
console.log("after");
}
console.log("done")
}.property("engagements")
})
Console log:
calling leaderboard
done
(setting engagements)
calling leaderboard
before
Version: Ember.js RC6, development

Turns out the property "engagements" was being set inside a promise fulfilment handler. This article explains how to catch errors that occur in those: http://blog.sensible.io/2013/06/10/promise-ate-my-homework-exception.html

Related

How to remove these deprecation on console on ember^2.0

while refreshing my site i am always getting some deprecation like this on console :
A property of <Ember.OutletView:ember666> was modified inside the didUpdate hook. You should never change properties on components, services or models during didUpdate because it causes significant performance degradation. [deprecation id: ember-views.dispatching-modify-property]
How to remove these deprecation on console on ember^2.0
I am not using Ember CLI.
Usually it means, that you need to do the work inside the didReceiveAttrs method, rather than the didUpdate. However, it you must have it in didUpdate, you can do something like this:
didUpdate() {
Ember.run.scheduleOnce('afterRender', this, => {
// some code
});
}
However it most likely will do some rendering twice (however it already does it twice - hence the deprecation).
Romans solution worked well for me, except for some syntax problems. I needed to set a default value to a child component. Heres the code:
initDefValue: function() {
const valEmpty = Ember.isEmpty(this.get("value"));
if (valEmpty) {
Ember.run.scheduleOnce('afterRender', this, () => {
this.sendAction("initValue", this);
});
}
}.on("didReceiveAttrs"),

Need help figuring out what this Ember unloadAll does

I have this route that currently, when I transition back to it, gives me this great big error with a stack trace that doesn't help me figure out what is going wrong.
Error while processing route: project.details Assertion Failed: calling set on destroyed object Error: Assertion Failed: calling set
on destroyed object
at new Error (native)
at Error.EmberError (http://starqa.fmr.com/assets/vendor.js:22615:21)
at Object.Ember.default.assert (http://starqa.fmr.com/assets/vendor.js:15716:13)
at Object.set (http://starqa.fmr.com/assets/vendor.js:26367:22)
at exports.default.mixin.Mixin.create.set (http://starqa.fmr.com/assets/vendor.js:41034:20)
at Ember.Object.extend.flushCanonical (http://starqa.fmr.com/assets/vendor.js:69769:14)
at ember$data$lib$system$relationships$state$has_many$$ManyRelationship.flushCanonical
(http://starqa.fmr.com/assets/vendor.js:71525:22)
at Queue.invoke (http://starqa.fmr.com/assets/vendor.js:11425:18)
at Object.Queue.flush (http://starqa.fmr.com/assets/vendor.js:11490:13)
at Object.DeferredActionQue
Through just going through my routes and commenting out stuff, I found this in my projects route:
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model: function(params) {
if (params.q) {
return this.store.find('project', params);
} else {
var _this = this;
Ember.run(function() {
_this.store.unloadAll('project');
});
return this.store.findAll('project', {reload: true});
}
}
And if I comment out lines 7-9:
/*
Ember.run(function() {
_this.store.unloadAll('project');
});
*/
then the error goes away and the transition worked. This bit of code was written by somebody else, and I think it has to do with refreshing the model from the store, but I can't figure out why it would cause this "calling set on a destroyed object" error.
Any help would be greatly appreciated.
Offhand it looks like this route serves both single project param (q is specified) and all projects, which offhand sounds like far from perfect design for ember. Ideally you should have two routes - the projects and project route. That's on the Ember architecture side.
On the functional side, this happens when you object was released by ember yet you try and access it a second time. I suspect this is happening as the Ember.run, runs the unload all in another loop, whereas I don't think that's what's needed. Try to remove the unload all from the ember loop, or most chances you can just run without it at all (as why do you want to remove all the object in the current cache each time you call the route?
this.store.unloadAll('project');
return this.store.findAll('project', {reload: true});
Or just leave it commented out (I think leaving it commented should work for you).

How to trigger `error` action *outside* of a transition

I'm looking to implement some consistent error handling in my app through the error action. The problem I've run into is that it is only triggered when an exception is raised while in a transition, and not, for example, in a plain saveModelInResponseToUserClick action on a route.
I can sort of get something to work with the following, but it's a hack:
Ember.onerror = function(error) {
MyApp.__container__.lookup('router:main').send('handleError')
}
With that, I could have different error-handling logic in differently-nested routes.
EDIT: Another issue with using the method above is when an error occurs before the app has fully transitioned into its first route - another exception is raised in that case and everything blows up.
Is there a different approach I can take with this?
As you said, the error action will only trigger while in transition.
For errors that may arise from an action, you could try using the following:
Ember.RSVP.on('error', function(error) {
// handle error
}
This will catch ANY error that occurs as a result of a promise in your app. You can access the "error" object inside the function, which will give you some detail as to what exactly went wrong, particularly the "responseText" attribute. The code itself goes in your app.js file.
Ember docs on this: http://emberjs.com/guides/understanding-ember/debugging/#toc_errors-within-an-code-rsvp-promise-code

How to throw Ember.js errors?

In an ember.js application, how can we throw application errors (and have them bubble through the controller-route-application hierarchy?)
My use case is related to catching non ember-data ajax errors and handling them through the same path as ember data errors.
(i.e. when experiencing an error from a non-restful endpoint, allow that error to bubble through the application similar to ember-data errors)
If you want to throw errors, use throw new Error("Message");.
The user gets redirected to error route.
With Promises you can react on Exceptions, and handle them.
See: http://emberjs.com/api/classes/RSVP.Promise.html
Ember has its own EmberError class which sub classes the Javascript error class.
import EmberError from '#ember/error';
export default Route.extend({
/* Pseudo code... */
model() {
if(/* something bad happens */) {
throw new EmberError('Oh, no! Something bad happened!');
}
},
});
You can do something with it in an error action in your route. If you want it to bubble up, remember to return true.
actions: {
error(error) {
// do something
return true;
},
},
Ember automagically creates an error substate and a error template where you can display info about the error (without redirecting). You can show error info in application-error.hbs or error.hbs like so:
<h1>{{model.name}} {{model.status}}</h1>
{{model.stack}}
See the Ember substate guide for more options.

How can I know the error reason in promise's rejection handler?

I wrote some code using find method like below.
The adapter is RESTAdapter.
App.SessionManager = Em.Object.extend({
userIdChanged: function() {
App.User.find(this.get('userid')).then(
function(user) {
/* process something */
},
function(error) {
/* rejection handler */
/* I want to know what error returned by the server here.*/
/* but how? */
}
);
}.observes('userid'),
});
If my server returned some error(e.g. 401) the rejection handler called.
But it seems that the argument of handler doesn't have error information.
How can I know the error reason in rejection handler?
Handling of errors returned by the server is not yet fully implemented in ember data.
For reference, as stated in this blog post about ember-data:
We want to make error handling and dealing with client and server conflicts rock solid. A pull request from Paul Chavard is currently open and looks like a solid starting point for error handling. You should see much more development on this in the near future.
But there are some workaround you can do to get to that information in the meanwhile.
For example:
Ember.RSVP.configure('onerror', function(error) {
console.log(error.message);
console.log(error.stack);
});
Or use a dirty hack to get to that information. Since ember-data uses jQuery under the hood you can subscribe to ajaxError:
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
// this will trigger anytime there is an error
});
Hope it helps.
you can also override this:
becameInvalid: function(record) {
// you can get errors just by doing record.errors, error keys must match
// the name of a field that you have defined in your model
}
and:
becameError: function(record) {
}
that's in case something happened in the server that caused an error. I just saw that you want to handle errors on promises, well, that's something different that I haven't dealt with. becameError might be fired.
UPDATE:
I just found something interesting that might help you: Ember-Data handling 401’s thanks to the new router, I haven't had the chance to use all those new features, but they look pretty cool.