坚持使用通用 ErrorHandler.js,同时允许对每个请求进行自定义错误消息处理,并且没有双消息框
Stick with generic ErrorHandler.js while allowing custom errormessage handling per request and not have double message boxes
通用的 ErrorHandler 是一个扩展并挂接到每个组件的主模型请求上,对于意外错误很有用。
但是,当我创建新实体时,我想使用用户友好的消息进行报告。这些消息在网关中组合并在 RAISE 子句中传递。目前,这会导致将消息框分开弹出,一个来自 ErrorHandler,一个来自我传递给 oModel.create().
的 onErrorHanlder
如何保留通用的,但在这种情况下不使用它?
要(暂时)从模型中分离错误处理程序,您必须调用附加到模型的 detachRequestFailed
处理程序。此处理程序在 ErrorHandler
的 constructor
中附加到您的模型。
但是,要分离此处理程序,您需要侦听器和函数。 handler 函数是一个匿名函数,当你想临时删除 handler 时,你不能轻易引用它。
当前交付的ErrorHandler
只显示第一条错误信息。它通过检查是否有一个消息框已经打开并且只在没有消息框打开时显示一个消息框来做到这一点。要禁止显示所有消息框,只需让 ErrorHandler
相信已经打开了一个消息框:this.component._oErrorHandler._bMessageOpen = true;
。一旦您完成了特殊服务和自定义处理程序,并想回到默认的 ErrorHandler,只需确保 ErrorHandler 认为没有消息框再打开:this.component._oErrorHandler._bMessageOpen = false;
可能更好的选择是编写您自己的 ErrorHandler
并确保处理错误的函数不是匿名的。通过这种方式,您可以轻松地将功能分离并重新附加到您的模型。
ErrorHandler.js
中所需的更改:更改 constructor
并添加 _metadataFailedHandler
和 _requestFailedHandler
constructor : function (oComponent) {
this._oResourceBundle = oComponent.getModel("i18n").getResourceBundle();
this._oComponent = oComponent;
this._oModel = oComponent.getModel();
this._bMessageOpen = false;
this._sErrorText = this._oResourceBundle.getText("errorText");
this._oModel.attachMetadataFailed(this._metadataFailedHandler, this);
this._oModel.attachRequestFailed(this._requestFailedHandler, this);
},
_metadataFailedHandler: function(oEvent) {
var oParams = oEvent.getParameters();
this._showMetadataError(oParams.response);
},
_requestFailedHandler: function(oEvent) {
var oParams = oEvent.getParameters();
// An entity that was not found in the service is also throwing a 404 error in oData.
// We already cover this case with a notFound target so we skip it here.
// A request that cannot be sent to the server is a technical error that we have to handle though
if (oParams.response.statusCode !== "404" || (oParams.response.statusCode === 404 && oParams.response.responseText.indexOf("Cannot POST") === 0)) {
this._showServiceError(oParams.response);
}
},
要分离错误处理程序:
this.getModel().detachRequestFailed(
this.component._oErrorHandler._requestFailedHandler,
this.component._oErrorHandler);
并在完成自定义请求和自定义处理程序后重新附加错误处理程序:
this.getModel().attachRequestFailed(
this.component._oErrorHandler._requestFailedHandler,
this.component._oErrorHandler);
为了添加来自 jpenninkhof 的上述响应,我有一个场景,即使在 oViewModel.update 之后(在我的情况下它是更新请求),也会引发 requestFailed 事件(可能事件卡在事件队列中)请求已完成。所以我想出了一个解决方案。
让我先解释一下这个问题。
我有一个对话框,用于使用 Save/Cancel 按钮编辑销售订单。保存时,oViewModel.update 被调用成功和错误处理函数。
this.getOwnerComponent().getModel().detachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler,this.getOwnerComponent()._oErrorHandler);
oViewModel.update(aObjectPath, aData, {
success: function(oData, oResponse) {
MessageToast.show("Request created successfully");
this.getOwnerComponent().getModel().attachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler, this.getOwnerComponent()._oErrorHandler);
},
error: function(oData, oResponse) {
MessageToast.show("Error updating Sales Order.");
this.getOwnerComponent().getModel().attachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler, this.getOwnerComponent()._oErrorHandler);
}});
ErrorHandler-->_requestFailedHandler 在错误函数之后被调用,因此通用错误弹出窗口仍然出现。我也在 oViewModel.attachRequestCompleted() 中尝试了 ErrorHandler-->attachRequestFailed() 但在完成 oData 请求后仍然调用 requestFailed 处理程序(可能是 bug/limitation)。
所以我在 ErrorHandler.js 中创建了另一个 Flag 以及一个回调函数。该标志阻止服务消息弹出(如 ErrorHandler-->_bMessageOpen)并调用回调让调用者知道 _showServiceError() 已被调用。
_showServiceError: function(sDetails) {
if (this._bServiceErrorOpen){
this._fnCallback();
return;
}
if (this._bMessageOpen) {
return;
}.....
}
再定义 2 个函数,一个用于设置标志和回调函数,另一个用于重置它。
setServiceErrorFlag: function(fnCallback){
this._bServiceErrorOpen = true;
this._fnCallback = fnCallback;
},
resetServiceErrorFlag: function(){
this._bServiceErrorOpen = false;
this._fnCallback = undefined;
}
在调用模型更新之前设置此标志。现在不会显示ServiceMessage,而是会调用匿名回调函数,等待while条件为false。
var that = this;
this._bErrorResponse = false;
this.getOwnerComponent()._oErrorHandler.setServiceErrorFlag(function()
{
while (that._bErrorResponse === false){}
that.getOwnerComponent()._oErrorHandler.resetServiceErrorFlag();
});
在 oViewModel.update() 的错误处理程序中,将 _bErrorResponse 设置为 true,以便退出 while 循环并重置 ErrorHandler 标志。这是为了确保仅在调用错误回调后才重置 ErrorHandler 标志。
error: function(oData, oResponse) {
MessageToast.show("Error updating Sales Order.");
that._bErrorResponse = true;
}
因此,ServiceError 消息被抑制,您可以在 oViewModel CRUD API 的错误函数回调中提供您自己的错误消息。
我知道它是一个较旧的 post 但是对于那些也有这个问题的人,我用一个 "quick and dirty way",一个临时标志变量 "bCustomError":[=12= 解决了它]
this.oModel.attachRequestFailed(function(oControlEvent) {
if (!that.bCustomError) {
/generic error handler
}
that.bCustomError = false;
});
现在有一个特定的处理程序:
this.bCustomError = true;
this.oModel.read("/XXX(sPath, {
success : this.onSuccessMethod.bind(this),
error : function(oError){ //custom error handling here }
});
通用的 ErrorHandler 是一个扩展并挂接到每个组件的主模型请求上,对于意外错误很有用。 但是,当我创建新实体时,我想使用用户友好的消息进行报告。这些消息在网关中组合并在 RAISE 子句中传递。目前,这会导致将消息框分开弹出,一个来自 ErrorHandler,一个来自我传递给 oModel.create().
的 onErrorHanlder如何保留通用的,但在这种情况下不使用它?
要(暂时)从模型中分离错误处理程序,您必须调用附加到模型的 detachRequestFailed
处理程序。此处理程序在 ErrorHandler
的 constructor
中附加到您的模型。
但是,要分离此处理程序,您需要侦听器和函数。 handler 函数是一个匿名函数,当你想临时删除 handler 时,你不能轻易引用它。
当前交付的ErrorHandler
只显示第一条错误信息。它通过检查是否有一个消息框已经打开并且只在没有消息框打开时显示一个消息框来做到这一点。要禁止显示所有消息框,只需让 ErrorHandler
相信已经打开了一个消息框:this.component._oErrorHandler._bMessageOpen = true;
。一旦您完成了特殊服务和自定义处理程序,并想回到默认的 ErrorHandler,只需确保 ErrorHandler 认为没有消息框再打开:this.component._oErrorHandler._bMessageOpen = false;
可能更好的选择是编写您自己的 ErrorHandler
并确保处理错误的函数不是匿名的。通过这种方式,您可以轻松地将功能分离并重新附加到您的模型。
ErrorHandler.js
中所需的更改:更改 constructor
并添加 _metadataFailedHandler
和 _requestFailedHandler
constructor : function (oComponent) {
this._oResourceBundle = oComponent.getModel("i18n").getResourceBundle();
this._oComponent = oComponent;
this._oModel = oComponent.getModel();
this._bMessageOpen = false;
this._sErrorText = this._oResourceBundle.getText("errorText");
this._oModel.attachMetadataFailed(this._metadataFailedHandler, this);
this._oModel.attachRequestFailed(this._requestFailedHandler, this);
},
_metadataFailedHandler: function(oEvent) {
var oParams = oEvent.getParameters();
this._showMetadataError(oParams.response);
},
_requestFailedHandler: function(oEvent) {
var oParams = oEvent.getParameters();
// An entity that was not found in the service is also throwing a 404 error in oData.
// We already cover this case with a notFound target so we skip it here.
// A request that cannot be sent to the server is a technical error that we have to handle though
if (oParams.response.statusCode !== "404" || (oParams.response.statusCode === 404 && oParams.response.responseText.indexOf("Cannot POST") === 0)) {
this._showServiceError(oParams.response);
}
},
要分离错误处理程序:
this.getModel().detachRequestFailed(
this.component._oErrorHandler._requestFailedHandler,
this.component._oErrorHandler);
并在完成自定义请求和自定义处理程序后重新附加错误处理程序:
this.getModel().attachRequestFailed(
this.component._oErrorHandler._requestFailedHandler,
this.component._oErrorHandler);
为了添加来自 jpenninkhof 的上述响应,我有一个场景,即使在 oViewModel.update 之后(在我的情况下它是更新请求),也会引发 requestFailed 事件(可能事件卡在事件队列中)请求已完成。所以我想出了一个解决方案。 让我先解释一下这个问题。 我有一个对话框,用于使用 Save/Cancel 按钮编辑销售订单。保存时,oViewModel.update 被调用成功和错误处理函数。
this.getOwnerComponent().getModel().detachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler,this.getOwnerComponent()._oErrorHandler);
oViewModel.update(aObjectPath, aData, {
success: function(oData, oResponse) {
MessageToast.show("Request created successfully");
this.getOwnerComponent().getModel().attachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler, this.getOwnerComponent()._oErrorHandler);
},
error: function(oData, oResponse) {
MessageToast.show("Error updating Sales Order.");
this.getOwnerComponent().getModel().attachRequestFailed(this.getOwnerComponent()._oErrorHandler._requestFailedHandler, this.getOwnerComponent()._oErrorHandler);
}});
ErrorHandler-->_requestFailedHandler 在错误函数之后被调用,因此通用错误弹出窗口仍然出现。我也在 oViewModel.attachRequestCompleted() 中尝试了 ErrorHandler-->attachRequestFailed() 但在完成 oData 请求后仍然调用 requestFailed 处理程序(可能是 bug/limitation)。
所以我在 ErrorHandler.js 中创建了另一个 Flag 以及一个回调函数。该标志阻止服务消息弹出(如 ErrorHandler-->_bMessageOpen)并调用回调让调用者知道 _showServiceError() 已被调用。
_showServiceError: function(sDetails) {
if (this._bServiceErrorOpen){
this._fnCallback();
return;
}
if (this._bMessageOpen) {
return;
}.....
}
再定义 2 个函数,一个用于设置标志和回调函数,另一个用于重置它。
setServiceErrorFlag: function(fnCallback){
this._bServiceErrorOpen = true;
this._fnCallback = fnCallback;
},
resetServiceErrorFlag: function(){
this._bServiceErrorOpen = false;
this._fnCallback = undefined;
}
在调用模型更新之前设置此标志。现在不会显示ServiceMessage,而是会调用匿名回调函数,等待while条件为false。
var that = this;
this._bErrorResponse = false;
this.getOwnerComponent()._oErrorHandler.setServiceErrorFlag(function()
{
while (that._bErrorResponse === false){}
that.getOwnerComponent()._oErrorHandler.resetServiceErrorFlag();
});
在 oViewModel.update() 的错误处理程序中,将 _bErrorResponse 设置为 true,以便退出 while 循环并重置 ErrorHandler 标志。这是为了确保仅在调用错误回调后才重置 ErrorHandler 标志。
error: function(oData, oResponse) {
MessageToast.show("Error updating Sales Order.");
that._bErrorResponse = true;
}
因此,ServiceError 消息被抑制,您可以在 oViewModel CRUD API 的错误函数回调中提供您自己的错误消息。
我知道它是一个较旧的 post 但是对于那些也有这个问题的人,我用一个 "quick and dirty way",一个临时标志变量 "bCustomError":[=12= 解决了它]
this.oModel.attachRequestFailed(function(oControlEvent) {
if (!that.bCustomError) {
/generic error handler
}
that.bCustomError = false;
});
现在有一个特定的处理程序:
this.bCustomError = true;
this.oModel.read("/XXX(sPath, {
success : this.onSuccessMethod.bind(this),
error : function(oError){ //custom error handling here }
});