Hi,
I’m trying to customize error and exception handling in my Web application.
So far, I’ve suppressed the default red error rectangle by setting:
Application.ErrorType := aeSilent;
I created two handlers that I then registered in the WebFormCreate of the main form:
procedure TForm1.AppError(Sender: TObject; AError: TApplicationError; var Handled: Boolean);
begin
Handled := true;
console.log('App Error');
end;
procedure TForm1.AppException(Sender: TObject; E: Exception);
begin
console.log('App Exception');
end;
Despite this, I still see other non-browser error messages in the console, which suggests not all errors are being caught by these handlers.
Is there a way to ensure all application-level errors and exceptions are routed through Application.OnError and Application.OnException, so I can fully control how they're handled?
Or a better way for manage error handling?
Thanks!
tl;dr: Some exceptions may surpass the default error handling, even if you think you caught them...
In your main form, have this:
Interface
// Global uncaught exception handling
Type
TAppErrorHandlerDummyClass = Class
Class Procedure OnAppError(Sender: TObject; AError: TApplicationError; var Handled: boolean); {$IFDEF PAS2JS} async; {$ENDIF}
End;
Procedure SetupGlobalErrorHandling;
Implementation
Function TApplicationErrorToException(AError : TApplicationError) : Exception;
Begin
Result := Nil;
{$IFNDEF WIN32}
ASM
{if ((AError.AError!==undefined) && (AError.AError!==null) &&
(AError.AError.FJSError!==undefined) && (AError.AError.FJSError!==null)) {
Result = AError.AError;
}}
END;
{$ENDIF}
If assigned(Result) then exit;
If AError.AMessage<>'Undefined JavaScript exception' then
Result := EJSException.Create(AError.AMessage);
End;
{--------------------------------------------------}
{ TAppErrorHandlerDummyClass }
Class Procedure TAppErrorHandlerDummyClass.OnAppError(Sender: TObject;
AError: TApplicationError; var Handled: boolean);
Var E : Exception;
Begin
Handled := True;
E := TApplicationErrorToException(AError);
If E=Nil then exit;
// If you like: your error handling here
// MyErrorHandlingHere(E);
End;
{---------------------------------------}
Procedure SetupGlobalErrorHandling;
Begin
{$IfDef PAS2JS}
// Catch JS Errors
ASM
window.onerror = function(message, source, lineno, colno, error) {
return true;
};
window.addEventListener("unhandledrejection", function(event) {
console.warn("Unhandled Promise Rejection:", event.reason);
event.preventDefault();
});
END;
{$EndIf}
End;
SetupGlobalErrorHandling to my knowledge stops all unwanted js internal error handling!
Then in your dpr file, add this before the first form is created:
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.ErrorType := aeSilent;
Application.OnError := TAppErrorHandlerDummyClass.OnAppError;
SetupGlobalErrorHandling;
Application.CreateForm(...
This finally silenced it for me once and for all.