我可以找到大量旧问题,询问/回答如何在Ember / Ember数据中处理来自Rails后端的401s。许多(如果不是全部)在这一点上似乎已经过时了。我已经尝试了所有可以找到的东西。 (Ember-Data handling 401’s)
但无论我做什么,我都会在控制台中不断收到401错误,而我的代码中永远不会收到401错误。我想要做的就是添加重定向到' /'如果在任何地方/模型/任何地方遇到过401。我不需要检查身份验证或其他任何事情。
我尝试将此添加到Application Route操作以及路由器本身。
error: function (error, transition) {
console.log("err: " + error.status);
if (error && error.status === 401) {
return this.transitionToRoute('/');
}
}
我还试过了https://stackoverflow.com/a/19063009/1850353的几种变体。
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;
}
});
我显然是个菜鸟,所以也许我在这里错过了一些简单的东西。我的console.log都没有被触发,除非它引发了一个新的错误,我试图让它运行起来。是否有最新的最佳做法'风格的做法?
答案 0 :(得分:3)
这里的其他两个答案都很好,并且可以正常工作,但有一些不受欢迎的警告恕我直言。
我强烈建议实施Ember.onerror
钩子。任何未经处理的承诺拒绝都会在那个钩子上结束。如果您使用的是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
}
};
}
}
如上所述,这将处理所有未被捕获的承诺拒绝。因此,这仍然为您提供了在组件中本地处理承诺的灵活性。例如:
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;
}
})
}
}
});
请注意,如果我们无法处理错误,请在上面的promise拒绝处理程序中重新抛出它。这是非常重要的。重新抛出错误将使任何其他链式承诺处理程序有机会处理它。如果不加以处理,它最终将会达到Ember.onerror
。
答案 1 :(得分:2)
使用Ember 1.13.8& Ember Data 1.13.9,我的认证路线使用:
actions: {
error: function(reason, transition) {
if (reason.errors[0].status === '401') {
this.transitionTo('sign-in');
}
}
}
答案 2 :(得分:1)
使用在控制器或路由中执行的逻辑,您通常会在路径上附加error
操作。如果在控制器上触发操作并且控制器未处理该操作(例如,控制器error
哈希中没有actions
操作)则会自动将其传递给路径以获取机会处理 - 如果当前路由没有处理该操作,它将起泡到父路由,直到它到达ApplicationRoute
。
我处理它的方式是AuthenticatedRoute
,任何需要处理401的路径都来自。此外,在您链接的示例中 - 它有events
,而现在是actions
。
这样的事情对你有用:
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
});
Ember正在越来越多地转向组件 - 在组件中执行逻辑的事情是它与其他所有东西完全隔离。通常,组件中可用的唯一内容就是您传递给它们的内容。
这意味着,如果您在组件中执行某些逻辑,则不使用上述逻辑 - 处理错误的路由上存在的逻辑 - 除非您自己明确使用它。
如果您在组件中调用store.find('person', 1)
或person.save()
,则需要使用.catch()
函数明确处理错误或将第二个函数传递给.then()
。例如,以下两个语句将执行相同的操作:
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);
});
这两个陈述也是如此:
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);
});
如果要将组件中的错误处理传递到路由上以处理最佳方法,请让组件触发操作并让调用模板/视图/控制器处理它。
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's bubbled up to the route to handle
-->
{{my-component model=model on-error='error'}}