我想要的是:全局处理不同http错误(401,404,500)的错误处理。发生http错误的地方或时间不重要。
到目前为止,我在应用程序路由中实现了一个错误操作,该操作将在路由model
挂钩上的任何适配器错误上调用。这很好。
当我在record.save()
等其他环境中使用记录时,未涵盖的内容就是这种情况。在那里,我需要单独处理承诺上的错误。
此外,我不想只有一个默认的错误处理程序,但更像是一个后备。
好的,在谈论太多之前,让我们举例说明我的用例。
申请路线
应用程序错误操作应该是默认/回退错误处理程序。
actions: {
error: function(error) {
var couldHandleError = false;
if (error.errors) {
switch (error.errors[0].status) {
case '401':
// User couldn't get authenticated.
// Redirect handling to login.
couldHandleError = true;
break;
case '404':
case '500':
// Something went unexpectedly wrong.
// Let's show the user a message
couldHandleError = true;
break;
}
}
// return true if none of the status code was matching
return !couldHandleError;
}
}
某些路线
在这种情况下,将调用应用程序错误操作。
model: function() {
return this.store.findAll('post');
}
某些控制器
在这种情况下,不会调用应用程序错误操作。
(我知道,以下代码可能没有意义,但它只是为了说明我的要求)
this.store.findRecord('post', 123);
其他一些控制器
在这个例子中,没有调用应用程序错误操作,因为我在这里使用自己的处理程序(catch()
)。
但正如您在评论中所看到的,我确实希望对404以外的所有状态代码使用默认处理程序。
this.store.findRecord('post', 123).catch(function(reason) {
if (reason.errors[0].status === '404') {
// Do some specific error handling for 404
} else {
// At this point I want to call the default error handler
}
});
有没有一种清洁和认可的方法来实现这一目标?我希望我能把问题告诉你。
答案 0 :(得分:14)
我想我有最后的解决方案,我希望与您分享。基本上我采纳了那些人评论我的问题的想法,并扩展他们以满足我的需要。
首先,我用主逻辑创建了一个mixin。因为我希望它尽可能通用,它区分a)控制器/路由和b)jquery /适配器错误。因此,从您调用它的位置以及您的错误对象最初是来自jquery Ajax请求还是ember适配器并不重要。
import Ember from 'ember';
export default Ember.Mixin.create({
ajaxError: function(error) {
if (!error) {
Ember.Logger.warn('No (valid) error object provided! ajaxError function must be called with the error object as its argument.');
return;
}
// Depending whether the mixin is used in controller or route
// we need to use different methods.
var transitionFunc = this.transitionToRoute || this.transitionTo,
couldHandleError = false;
switch (this._getStatusCode(error)) {
case 401:
transitionFunc.call(this, 'auth.logout');
couldHandleError = true;
break;
case 404:
case 500:
// Here we trigger a service to show an server error message.
// This is just an example and currently not the final implementation.
// this.get('notificationService').show();
couldHandleError = true;
break;
}
// For all other errors just log them.
if (!couldHandleError) {
Ember.Logger.error(error);
}
},
_getStatusCode: function(error) {
// First check for jQuery error object
var status = error.status;
// Check for ember adapter error object if it's not a jquery error
if (!status && error.errors && error.errors[0].status) {
status = parseInt(error.errors[0].status);
}
return status;
},
});
接下来,我重新打开了一些类(在app.js中)以使这个功能全局可用:
import AjaxErrorMixin from 'app/mixins/ajax-error';
Ember.Route.reopen(AjaxErrorMixin);
Ember.Controller.reopen(AjaxErrorMixin);
Ember.Component.reopen({
_actions: {
// Passing ajaxError per default
ajaxError: function(error) {
this.sendAction('ajaxError', error);
}
}
});
最后,我在应用程序路径中添加了一些操作:
actions: {
error: function(error) {
this.send('ajaxError', error);
},
ajaxError: function(error) {
this.ajaxError(error);
},
}
为什么我有两个动作做同样的事情?好吧,error
动作是在路由模型钩子上的错误上调用的。我可以继续使用该操作,但在我明确调用此操作的应用程序的其余部分中,我想要一个更有意义的名称。因此,我还创建了ajaxError
动作。你肯定可以坚持一个动作。
现在你可以在任何地方使用它:
路线/控制器:
this.ajaxError(error);
组件:
this.sendAction('ajaxError', error);
当然,您还需要将操作传递出应用程序路径要处理的组件:
{{some-component ajaxError="ajaxError"}}
这也适用于嵌套组件。您不需要在component.js文件中进一步显式发送此操作,因为我们重新打开了Component并将此操作传递给。
我希望我能帮助其他人实现这一目标。也欢迎任何反馈。
答案 1 :(得分:5)
您可以尝试对这些事件做一些事情(在app初始化之前将这些行放在app.js中):
Ember.onerror = function (error) {
console.log('Ember.onerror handler', error.message);
};
Ember.RSVP.on('error', function (error) {
console.log('Ember.RSVP error handler', error);
});
Ember.Logger.error = function (message, cause, stack) {
console.log('Ember.Logger.error handler', message, cause, stack);
};
我从https://raygun.io/blog/2015/01/javascript-error-handling-ember-js/了解了它们,你可能会在那里找到一些细节。