2
votes

I have a route /users/:user_id in emberjs application and I am assigning a model to the template in setupController hook of a App.UserRoute class as:

controller.store.find('user', model.id).then(onSuccess, onError);

var onSuccess = function(user) {

if(user) {
    // reload Model to forcefully fetch from server
    user.reload().then(function() { /* some processing */ }, function(error_response) { /* some error handling */ });

    // assign model for user
        controller.set('model', user);
    }
};

var onError = function(reason) { /* some error handling */ };

Now this gives me an error 404 from server when I am looking for an user-id which does not exists. I am trying to catch this error and display appropriate message and redirect to the list of all users (/users). But I am unable to catch it and I get an error from ember : Error while loading route: undefined. How can I achieve this?

3

3 Answers

1
votes

The real thing is you are passing in undefined to your then method. You should move your declaration of your callback functions to before the promise code.

var onSuccess = function(user) {

  if(user) {
    // reload Model to forcefully fetch from server
    user.reload().then(function() { /* some processing */ }, function(error_response) { /* some error handling */ });

    // assign model for user
        controller.set('model', user);
    }
  };

var onError = function(reason) { /* some error handling */ };

controller.store.find('user', model.id).then(onSuccess, onError);
0
votes

The reason is that you yourself are catching the failure and processing it via the second argument to then. This turns failure into success. You will need to rethrow the error so it is picked up by the error hook you have defined. One way would be

user.reload().then(
    function() { /* some processing */ }, 
    function(error_response) { /* some error handling */ }.catch(RSVP.rethrow)
});

It would also most likely work to do

user.reload().then(function() { /* some processing */ }, 
    function(error_response) { 
        /* some error handling */
        throw "reload failed";
    }
);

More generally, consider the following code:

rejected_promise.then(
    success1 /* won't be called */
    function rejected() { return 0; }
)
.then(
    success2 /* will be called */
    rejected2 /* won't be called */
);

Here, rejected2 won't be called; rather, success2 will be. That is because a rejection handler is considered to fulfill the promise (make it succeed), unless it rethrows.

0
votes

There are some implementation details that I think could be improved:

1) You do not need to set your model in the controller. Ember assigns it to the value resolved by the promise in the route model hook.

model: function(params) {

  var user = this.store.getById('user', params.id);

  if (user) {
    return user.reload();
  } else {
    return this.store.find('user', params.id);
  }

}

2) You could catch your promise error in the error event handler of your route.

    actions: {
      error: function(error) {
         // print error
        this.transitionTo('users');
      }
    }

You could take a look at the Ember Guide to check how Error and Loading substates are managed by the router.