What happens when ember's model hook's request fails - ember.js

I have a typical scenario.
My model hook for Route-1 looks something like this.
model() {
return Ember.RSVP.hash({
posts: this.store.findAll('post'),
authors: this.store.findAll('author')
});
}
If I'm on Route-2 and navigate to Route-1 it will call the model hook.
And if I already have data on my store, both the findAll requests are resolved, triggering RSVP.hash to resolve.
But if the request fails, I'm getting undefined error in my console (chrome).(twice for each of findAll)
My error tracking system reports it as Unhandled promise error detected
the stack shows no relevant info either
defaultDispatch # ember.debug.js:18008
dispatchError # ember.debug.js:17987
onerrorDefault # ember.debug.js:31634
trigger # ember.debug.js:58713
(anonymous) # ember.debug.js:59614
invokeWithOnError # ember.debug.js:346
flush # ember.debug.js:405
flush # ember.debug.js:529
end # ember.debug.js:599
(anonymous) # ember.debug.js:1165
I am not able to figure out what is causing the error to be thrown because the promise findAll already got resolved. And ember tells me I have not handled the promise!
I tried putting catch/reject codes everywher but it never gets called. Because of course the promise was already resolved. So, it can not be rejected.
Then where is this error coming from!! I have no clue. There is no error till the adapter returns.
The only thing I could find was in my serializer normalizeFindAllResponse was not invoked whenever such failures happened.
Any help is greatly appreciated. Thanks!

I somehow solved this issue.
Before, in my adapter I was rejecting the promise with Promis' reason object.
Now, in case of error response, I am rather sending an object containing errors array, rather then failure reason object.
So, the object will get passed as payload to my normalizeFindAllResponse in serializer. There I check for existance of errors array in our payload parameter.
If there is such object then just return an empty object with data attribute set to empty array.
Note: Got the idea from here.

Related

findRecord() returns error but record is returned properly

I have a strange error when calling data store's findRecord() function. Below is the function call inside of a route,
return this.get('store').findRecord('restaurant', params.restaurant_id);
And here are the errors I get,
vendor-6605726….js:10 Error while processing route: admin.restaurants.show e.getRecord is not a function TypeError: e.getRecord is not a function
vendor-6605726….js:8 TypeError: e.getRecord is not a function
The strangest thing is that the function works as it should since I can see using ember inspector that the query executes properly and returns the correct record. I have an index route that calls findAll() that does not throw any errors. I am formatting my json correctly I believe so I am out of ideas on what this could me.
Here is the json,
{"data":[{"type":"restaurants","id":1,"attributes":{"user_id":1,"name":"###########","address":"","phone":"##########","website":"##########","created_at":"2017-03-19 20:42:02","updated_at":"2017-03-19 20:42:02","description":"###########"}}]}
I recently had the same issue. It is highly likely that the JSON payload returned by your API isn't formatted correctly. Remember that findRecord() expects a single object to be returned, not an array:
{"data": {}}
not
{"data": []}
Double-check DevTools to see what your API returns to the client - make sure it's not an array.

Display global/misc error message to user

I'm trying to display error messages for the user in Ember. Is there a way to do this from Logger? I've read about the error substate, but I think that only displays when there's an error in a transition. Is there a way for me to set a property in the ApplicationController to the error message object (and thus display it in a template)? If there's an error in an AJAX call, or a bug, or some other issue, I want the user to be notified that something is awry.
The Coffeescript:
Ember.Logger.error = (message, cause, stack) ->
console.error(message, cause, stack) #show in console
Raygun.send(new Error(message), null, { cause: cause, stack: stack }) #log error on server
# how do I display the error message to user?, THIS DOESN'T WORK b/c "this" is undefined:
#container.lookup('controller:main').set('errorObjetct', message)
I'm using Ember 1.11.1 in ember-cli.
Anyone have any tips on this?
Bryan
Thanks #blessenm for the link. It doesn't precisely apply because in Ember-CLI I don't reference the global application variable, it did remind me that the initialize function passes the "container" object. Thus, I've been able to make it work like this:
Ember.Logger.error = (message, cause, stack) ->
console.error(message, cause, stack) #show in console
Raygun.send(new Error(message), null, { cause: cause, stack: stack }) #log error on server
# SOLUTION:
container.lookup('route:application').set('errorObject', message)
This runs in initializers/error-handling.coffee's initialize function.

Loopback: return error from beforeValidation hook

I need to make custom validation of instance before saving it to MySQL DB.
So I perform (async) check inside beforeValidate model hook.
MyModel.beforeValidate = function(next){
// async check that finally calls next() or next(new Error('fail'))
}
But when check fails and I pass Error obj to next function, the execution continues anyway.
Is there any way to stop execution and response to client with error?
This is a known bug in the framework, see https://github.com/strongloop/loopback/issues/614
I am working on a new hook implementation that will not have issues like the one you have experienced, see loopback-datasource-juggler#367 and the pull request loopback-datasource-juggler#403

Getting "Error: Assertion Failed: calling set on destroyed object" when trying to rollback a deletion

I am looking into how to show proper deletion error message in ember when there is an error coming back from the server. I looked at this topic and followed its suggestion:
Ember Data delete fails, how to rollback
My code is just like it, I return a 400 and my catch fires and logs, but nothing happens, when I pause it in the debugger though and try to rollback, I get Error: Assertion Failed: calling set on destroyed object
So A) I cannot rollback B) the error is eaten normally.
Here is my code
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
});
In case it's relevant, my model does have multiple relationships. What am I doing wrong? Ember-data version is 1.0.0.8 beta (previous one from the release a few days ago).
Thanks in advance.
EDIT
I discovered now that the record actually is restored currently inside the cache according to ember inspector, but the object will not reappear in the rendering of the visitors. I need some way to force it to reload into the template...
After destroyRecord, the record is gone and the deletion cannot be rolled back. The catch clause will just catch a server error. If you want the record back, and think it's still on the server, you'll have to reload it.
See the following comment on deleteRecord from the Ember Data source:
Marks the record as deleted but does not save it. You must call
`save` afterwards if you want to persist it. You might use this
method if you want to allow the user to still `rollback()` a
delete after it was made.
This implies that a rollback after save is not possible. There is also no sign anywhere I can see in the Ember Data code for somehow reverting a record deletion when the DELETE request fails.
In theory you might be able to muck with the isDeleted flag, or override various internal hooks, but I'd recommend against that unless you really know how things work.
Try reloading the model after the rollback. It will reload from the server but it was the only way around this that I could find.
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
visitor.reload().then(function(vis)
{
console.log('visitor.reload :: ' + JSON.stringify(vis));
});
});
Hope that helps.

Debugging Ember.js errors: Error while loading route

While in any particular case there are hints and clues on how to debug an error you get, I haven't really found a general Ember strategy.
For example, a typeError while loading a route:
Assertion failed: Error while loading route: TypeError: 'undefined' is not an object (evaluating 'window.router.lander') (ignore the fact that I'm trying to access window.router.lander. It's irrelevant)
Why does Ember not tell you which route it's loading when this error happens? Or whether it happens in afterModel(), or activate()? And what's the general strategy for finding that sort of context info?
So far all I've got is adding a bunch of console.logs scattered around. For example with the error above:
1) Find all occurrences of window.router.lander in my code
2) before the first occurrence, add a console.log('is it the first occurrence?'), and after the first occurrence put a console.log('its not the first occurrence')
3) Do the same for every occurrence
4) refresh. One of the 'is it the nth occurrence?' won't have a closer, and now you know where the error happened.
For better debugging, you can enable transitions logging by create app with LOG_TRANSITIONS and/or LOG_TRANSITIONS_INTERNAL properties:
window.App = Ember.Application.create({
// Basic logging, e.g. "Transitioned into 'post'"
LOG_TRANSITIONS: true,
// Extremely detailed logging, highlighting every internal
// step made while transitioning into a route, including
// `beforeModel`, `model`, and `afterModel` hooks, and
// information about redirects and aborted transitions
LOG_TRANSITIONS_INTERNAL: true
});
Referenece: http://emberjs.com/guides/understanding-ember/debugging/
Also, you can use canary build which provide detailed error stack:
http://emberjs.com/builds/#/canary
Ember isn't particularly helpful when it comes to errors in the model hook, or the promises it returns. I'm sure I've read in one of the issues (or http://discuss.emberjs.com/ I'm not sure) that this is an open issue in which they're working.
What I do is use the Chrome Developer Tools to debug the issue (instead of just console loggin it). From my experience it's usually:
you're not returning anything in the model hook
an error inside one of the then functions on the promise the model hook returns
I hope it helps you!