Sooner or later every TMS WEB Core application shows a block of white text on a bright red background across the bottom of the page - the error message, a JavaScript stack trace and a small X to close it. It is useful while you are writing the code. In front of a user it looks like the application has crashed, even when the error was minor and already reported.
This article explains where the red panel comes from, why try ...
except does not stop it, and how to replace it with a normal message for every
error - Pascal and JavaScript alike.
The panel is drawn by TApplication in WEBLib.Forms. When the
application starts, it adds listeners for the browser's error and
unhandledrejection events, so it sees every error that nothing else has handled.
What it does with them depends on Application.ErrorType:
alert boxThe default is aeSilent, but in a build with DEBUG defined it is
switched to aeFooter. So the panel only appears in Debug builds - which is exactly what
you are running while an application is still settling down, often on the live server too.
In the browser, almost every call to a server is asynchronous. Your code starts the request
and carries on; the reply arrives later and is handled in a callback. An exception raised in
that callback has no try block above it - the code that started the request has
long since finished - so it escapes to the browser, and TMS WEB Core shows it in red.
A common example is an XData dataset that the user is not allowed to read. When the server refuses with 403 Forbidden, the request fails like this:
TXDataWebDataSet.Load starts the request and returns at once.TXDataWebClient to fetch the
records, with no error handler of its own.EXDataClientRequestException inside
its reply callback.Wrapping Load in try ... except changes nothing,
because by the time the exception is raised, Load has already returned.
// This does NOT catch a 403 from the server
try
XDataWebDataSet1.Load;
except
on E: Exception do
ShowMessage(E.Message);
end;
TApplication offers two events, and the order in which it uses them matters.
For each unhandled error it:
Exception);Two things follow from this. You cannot hide the panel from OnError, because
by the time it runs the panel is already on the screen. And OnException on its
own is not enough, because plain JavaScript errors - from an asm block, a browser
API or a library such as Bootstrap - never reach it.
Turn the panel off, show Pascal exceptions from OnException, and use
OnError to catch whatever OnException did not see. A flag stops the
same error being shown twice, since a Pascal exception passes through both events.
type
TMainForm = class(TWebForm)
procedure WebFormCreate(Sender: TObject);
private
FErrorShown: Boolean;
procedure ApplicationException(Sender: TObject; E: Exception);
procedure ApplicationError(Sender: TObject; AError: TApplicationError;
var Handled: Boolean);
end;
implementation
procedure TMainForm.WebFormCreate(Sender: TObject);
begin
Application.ErrorType := aeSilent;
Application.OnError := ApplicationError;
Application.OnException := ApplicationException;
end;
// Pascal exceptions - called first
procedure TMainForm.ApplicationException(Sender: TObject; E: Exception);
begin
FErrorShown := True;
ShowMessage(E.Message);
end;
// Every error - called last. Plain JavaScript errors only arrive here.
procedure TMainForm.ApplicationError(Sender: TObject; AError: TApplicationError;
var Handled: Boolean);
begin
if not FErrorShown then
ShowMessage(AError.AMessage);
FErrorShown := False;
Handled := True;
end;
With this in place:
ApplicationException; ApplicationError then sees the flag, skips
it and clears the flag. A JavaScript error skips ApplicationException, so
ApplicationError shows it.OnCreate, before
anything asynchronous starts, so the first error is caught too.E.Message or AError.AMessage and AError.AStack to
the browser console with console.log, or send them to your server, so you can
still find the cause.ShowMessage keeps the example short; any
dialog of your own works the same way.OnError
parameter of TXDataWebClient.RawInvoke - handle the error there, with a message
that means something to the user.
Please donate if helpful