Backbone.js同步错误处理 #
一、错误类型 #
1.1 常见错误类型 #
text
同步错误类型
├── HTTP错误:401、403、404、500等
├── 验证错误:服务器端验证失败
├── 网络错误:连接超时、断网
└── 解析错误:JSON解析失败
1.2 错误响应格式 #
json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "验证失败",
"details": {
"name": ["不能为空"],
"email": ["格式不正确"]
}
}
}
二、错误回调 #
2.1 基本错误处理 #
javascript
user.fetch({
success: function(model, response) {
console.log('成功:', response);
},
error: function(model, xhr, options) {
console.log('失败:', xhr.status, xhr.statusText);
}
});
2.2 error事件 #
javascript
user.on('error', function(model, xhr, options) {
console.log('模型错误:', xhr.status);
});
user.fetch();
2.3 invalid事件 #
javascript
user.on('invalid', function(model, error, options) {
console.log('验证失败:', error);
});
user.save({ name: '' }, { validate: true });
三、HTTP错误处理 #
3.1 状态码处理 #
javascript
user.fetch({
error: function(model, xhr) {
switch (xhr.status) {
case 400:
console.log('请求参数错误');
break;
case 401:
console.log('未授权,请登录');
break;
case 403:
console.log('禁止访问');
break;
case 404:
console.log('资源不存在');
break;
case 422:
console.log('验证错误');
break;
case 500:
console.log('服务器错误');
break;
default:
console.log('未知错误');
}
}
});
3.2 全局错误处理 #
javascript
$(document).ajaxError(function(event, xhr, settings, error) {
switch (xhr.status) {
case 401:
Backbone.history.navigate('login', { trigger: true });
break;
case 403:
alert('您没有权限执行此操作');
break;
case 500:
alert('服务器错误,请稍后重试');
break;
}
});
3.3 认证错误处理 #
javascript
var AuthHandler = {
handle401: function() {
localStorage.removeItem('token');
Backbone.history.navigate('login', { trigger: true });
},
setup: function() {
$(document).ajaxError(function(event, xhr) {
if (xhr.status === 401) {
this.handle401();
}
}.bind(this));
}
};
AuthHandler.setup();
四、验证错误处理 #
4.1 服务器验证错误 #
javascript
user.save(attrs, {
error: function(model, xhr) {
if (xhr.status === 422) {
var errors = xhr.responseJSON.errors;
model.trigger('validation:error', errors);
}
}
});
4.2 显示验证错误 #
javascript
var UserFormView = Backbone.View.extend({
events: {
'submit': 'submit'
},
initialize: function() {
this.listenTo(this.model, 'validation:error', this.showErrors);
this.listenTo(this.model, 'invalid', this.showInvalidError);
},
submit: function(e) {
e.preventDefault();
var data = {
name: this.$('#name').val(),
email: this.$('#email').val()
};
this.model.save(data, {
error: function(model, xhr) {
if (xhr.status === 422) {
model.trigger('validation:error', xhr.responseJSON.errors);
}
}
});
},
showErrors: function(errors) {
this.clearErrors();
for (var field in errors) {
var $field = this.$('[name="' + field + '"]');
$field.addClass('error');
$field.after('<span class="error-message">' + errors[field].join(', ') + '</span>');
}
},
showInvalidError: function(model, error) {
this.$('.alert').text(error).show();
},
clearErrors: function() {
this.$('.error').removeClass('error');
this.$('.error-message').remove();
}
});
五、网络错误处理 #
5.1 超时处理 #
javascript
user.fetch({
timeout: 10000,
error: function(model, xhr) {
if (xhr.statusText === 'timeout') {
console.log('请求超时');
}
}
});
5.2 重试机制 #
javascript
var RetryMixin = {
maxRetries: 3,
retryDelay: 1000,
fetchWithRetry: function(options) {
var self = this;
var retries = 0;
options = options || {};
function attempt() {
return self.fetch(options).fail(function(xhr) {
if (xhr.status >= 500 && retries < self.maxRetries) {
retries++;
console.log('重试第', retries, '次');
return $.Deferred(function(deferred) {
setTimeout(function() {
attempt().done(deferred.resolve).fail(deferred.reject);
}, self.retryDelay * retries);
});
}
});
}
return attempt();
}
};
5.3 离线处理 #
javascript
var OfflineHandler = {
isOnline: function() {
return navigator.onLine;
},
setup: function() {
$(window).on('offline', function() {
console.log('网络已断开');
this.showOfflineMessage();
}.bind(this));
$(window).on('online', function() {
console.log('网络已恢复');
this.hideOfflineMessage();
}.bind(this));
},
showOfflineMessage: function() {
$('body').append('<div id="offline-message" class="alert">您已离线</div>');
},
hideOfflineMessage: function() {
$('#offline-message').remove();
}
};
OfflineHandler.setup();
六、错误显示 #
6.1 通知服务 #
javascript
var NotificationService = _.extend({
show: function(type, message) {
var $notification = $(
'<div class="notification notification-' + type + '">' +
' <span>' + message + '</span>' +
' <button class="close">×</button>' +
'</div>'
);
$notification.find('.close').on('click', function() {
$notification.remove();
});
$('#notifications').append($notification);
setTimeout(function() {
$notification.fadeOut(function() {
$(this).remove();
});
}, 5000);
},
success: function(message) {
this.show('success', message);
},
error: function(message) {
this.show('error', message);
},
warning: function(message) {
this.show('warning', message);
},
info: function(message) {
this.show('info', message);
}
}, Backbone.Events);
6.2 全局错误处理 #
javascript
var GlobalErrorHandler = {
setup: function() {
$(document).ajaxError(function(event, xhr, settings, error) {
var message;
switch (xhr.status) {
case 0:
message = '网络连接失败,请检查网络';
break;
case 400:
message = '请求参数错误';
break;
case 401:
message = '登录已过期,请重新登录';
Backbone.history.navigate('login', { trigger: true });
break;
case 403:
message = '您没有权限执行此操作';
break;
case 404:
message = '请求的资源不存在';
break;
case 422:
var errors = xhr.responseJSON && xhr.responseJSON.errors;
if (errors) {
message = Object.values(errors).join(', ');
} else {
message = '数据验证失败';
}
break;
case 500:
message = '服务器错误,请稍后重试';
break;
default:
message = '未知错误: ' + xhr.status;
}
NotificationService.error(message);
});
}
};
GlobalErrorHandler.setup();
七、实用示例 #
7.1 错误处理模型 #
javascript
var ErrorHandlingModel = Backbone.Model.extend({
fetch: function(options) {
var self = this;
this.trigger('request:start');
options = options || {};
var success = options.success;
var error = options.error;
options.success = function() {
self.trigger('request:end');
self.trigger('request:success');
if (success) success.apply(this, arguments);
};
options.error = function(xhr) {
self.trigger('request:end');
self.trigger('request:error', xhr);
self.handleError(xhr);
if (error) error.apply(this, arguments);
};
return Backbone.Model.prototype.fetch.call(this, options);
},
handleError: function(xhr) {
var error = {
status: xhr.status,
message: this.getErrorMessage(xhr),
details: xhr.responseJSON
};
this.lastError = error;
this.trigger('error', this, error);
},
getErrorMessage: function(xhr) {
if (xhr.responseJSON && xhr.responseJSON.message) {
return xhr.responseJSON.message;
}
switch (xhr.status) {
case 401: return '未授权';
case 403: return '禁止访问';
case 404: return '资源不存在';
case 500: return '服务器错误';
default: return '请求失败';
}
}
});
7.2 错误处理视图 #
javascript
var ErrorHandlingView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'request:start', this.showLoading);
this.listenTo(this.model, 'request:end', this.hideLoading);
this.listenTo(this.model, 'request:error', this.showError);
},
showLoading: function() {
this.$('.loading').show();
},
hideLoading: function() {
this.$('.loading').hide();
},
showError: function(xhr) {
var message = this.model.getErrorMessage(xhr);
this.$('.error-message').text(message).show();
}
});
八、总结 #
8.1 错误处理方法 #
| 方法 | 说明 |
|---|---|
| error回调 | 单次请求错误处理 |
| error事件 | 模型级别错误处理 |
| ajaxError | 全局错误处理 |
8.2 最佳实践 #
- 实现全局错误处理
- 统一错误显示方式
- 处理认证错误
- 实现重试机制
- 处理离线状态
最后更新:2026-03-28