401s carbon treatment renewed in 2015

I can find a ton of old questions that ask / answer how to handle 401s from the Rails backend in Ember / Ember Data. Many, if not all, are currently out of date. I tried everything I could find. ( Processing Ember-Data 401s )

But no matter what I do, I just keep getting 401 errors in the console, and 401 never gets into my code. All I want to do is add a redirect to "/" if 401 is ever found anywhere / model / anywhere. I don't need authentication or anything else.

I tried to add this to Application Route activities, as well as to the router itself.

error: function (error, transition) { console.log("err: " + error.status); if (error && error.status === 401) { return this.transitionToRoute('/'); } } 

I have also tried several variations of this https://stackoverflow.com/a/360960/

 App.ApplicationAdapter = DS.RESTAdapter.extend({ ajaxError: function(jqXHR) { var error = this._super(jqXHR); console.log("jqXHR: " + jqXHR.status); if (jqXHR && jqXHR.status === 401) { #handle the 401 error } return error; } }); 

I am obviously a noob, so maybe I missed something simple here. None of my console.log starts, unless for the new error that I presented, trying to get this to work. Is there a way to create a “best practice” style?

+4
source share
3 answers

Controllers and routes

With logic running in a controller or route, you usually use the error action attached to the route. If the action is run on the controller and the controller does not process this action (for example, the action hash controller does not have an error action), it is automatically transferred to the route in order to be able to process it - if the current route does not process the action, or it bubbles on the parent routes, until it reaches ApplicationRoute .

As I process it, there is an AuthenticatedRoute from which any route that should handle 401 extends. In addition, in the example to which you are attached, it has events , whereas now actions .

Something like this should work for you:

  App.AuthenticatedRoute = Ember.Route.extend({ actions: { error: function(error) { if (!error || error.status !== 401) { // returning true bubbles the error to parent routes return true; } // put your logic here console.log('this is a 401 error.'); } } }); App.IndexRoute = App.AuthenticatedRoute.extend({ //logic }); App.FooRoute = App.AuthenticatedRoute.extend({ //logic }); App.BarRoute = App.AuthenticatedRoute.extend({ //logic }); 

Components

Ember is moving more and more towards components - the thing with the logic executed in the components is that it is completely isolated from everything else. As a rule, the only thing that is available to you in your components is what you pass on to them.

This means that if you execute any logic in the component, then none of the above logic - the logic that exists on the routes for error handling, is used if you do not explicitly use it yourself.

If you call calls like store.find('person', 1) or person.save() in the component, you need to explicitly handle the errors using the .catch() function or pass the second function to .then() . For example, the following two statements will do the same:

  store.find('person', 1).then(function(person) { console.log('found person 1:', person); }, function(err) { console.log('error finding person 1:', err); }); store.find('person', 1).then(function(person) { console.log('found person 1:', person); }).catch(function(err) { console.log('error finding person 1:', err); }); 

And so would these two statements:

  person.save().then(function() { console.log('successfully saved person'); }, function(err) { console.log('error saving person:', err); }); person.save().then(function() { console.log('successfully saved person'); }).catch(function(err) { console.log('error saving person:', err); }); 

Reusing Route Error Logic in Components

If you want to transfer error handling in your components on your routes, in order to deal with the best way to do this, you need the component to start the action and process the calling template / view / controller.

app/components/my-component.js

  Ember.Component.extend({ 'on-error': null, model: null, actions: { save: function() { var component = this; var model = this.get('model'); mode.save().then(function() { console.log('saved'); }).catch(function(err) { component.sendAction('on-error', err); }); } } }); 

app/templates/components/my-component.hbs

  <button {{action 'save'}}>Save</button> 

app/templates/index.hbs

  <!-- Passing the 'error' action to the components 'on-error' property links the 'on-error' action on the component with the 'error' action on the controller - if the controller doesn't handle it, it bubbled up to the route to handle --> {{my-component model=model on-error='error'}} 
+1
source

Both of the other two answers here are good and will work fine, but have a few unwanted IMHO caveats.

I would highly recommend using the Ember.onerror hook. Any unmanageable promises will end up on this hook. You can implement it with an initializer if you use Ember-CLI.

 // app/initializers/on-error.js export default { name: 'on-error', initialize: function(container, app) { Ember.onerror = function(error) { if(error && error.status === 401) { // Ember 2.1 adds a public lookup function. Older versions // need to use the container. var router = app.lookup ? app.lookup('router:main') : app.__container__.lookup('router:main'); // Even future versions of ember are likely to have an // accessible router service to do this work. router.transitionTo('sign-in'); } if(error && error.stack) { // Uncaught exception - Log stacktrace to server } }; } } 

As mentioned above, this will handle all the fuzzy promises. Thus, this still provides you with a little flexibility when working with promises locally in a component. For instance:

 export default Ember.Component.extend({ actions: { saveChanges: function() { this.get('model').save().then(null, (reason) => { if(/* reason is validation error */) { this.set('validationError', reason.errorMsg); } else { throw reason; } }) } } }); 

Please note that in the promise rejection handler above, if we cannot handle this error, we will recreate it. It is very important. A repeated error will result in any additional promise handler making it possible to handle this. And ultimately it will reach the Ember.onerror level if left untreated.

+3
source

Using Ember 1.13.8 and Ember Data 1.13.9, my authenticated routes use:

 actions: { error: function(reason, transition) { if (reason.errors[0].status === '401') { this.transitionTo('sign-in'); } } } 
+2
source

Source: https://habr.com/ru/post/984716/


All Articles