Edit Narrowed it down to this 1 line,
HTML := wb.OleObject.Document.documentElement.innerHTML;
which consumes the time... how can that be speed up?
Using the following code my application can hang for 1-2 seconds while it tries to access the HTML of a page (Delphi XE).
function Button1Click(Sender : TObject);
begin
wb.navigate('http://10.0.0.154/stats');
// Use a timer to poll the page - dont wait and process app messages
timer1.enabled := true;
end;
procedure Timer1Timer(Sender : TObject);
var
HTML : WideString;
begin
If GetHTML(HTML) = true then
begin
Timer1.enabled := false;
{ do something }
end;
end;
function GetHTML(var HTML : WideString) : boolean;
var
Document : IHTMLDocument2;
begin
HTML := '';
Result := false;
Document := wb.DOcument as IHTMLDocument2;
If Assigned(Document) then
begin
try
HTML := wb.OleObject.Document.documentElement.innerHTML;
Result := true;
except
Result := false;
end;
end;
end;
However I notice in my GetHTML method can take 1-2 seconds to return something and it locks UI. Looking at the AQTime with Delphi XE it says that method call is slow (1-2 seconds). It's sporatic and I wonder if it fails when the page is still mid load.
The page I am loading is an inhouse page, full of javascript and 500k big, I can't use the OnDocumentComplete because it fires before the page is even ready, even if I do a check on the ReadyState it still fires to early.
Anyone able to shed some light, if their a faster way I can access the HTML of TWebbrowser?
Your problem appears to be that you are not allowing TWebBrowser to complete the loading of the page before you try to get the HTML. This is only a guess because you do not show how the code where you call wb.Navigate and you are having to deal with exceptions getting the InnerHTML.
You should try the following:
As with @crefird's answer, I suspect you are attempting to access the InnerHTML before the browser has completed its work...
If ReadState/Busy are not returning accurate representations of the TWebBrowser's busy state, you can do this:
1) Create either a global variable, or a private member of your form... such as "FBrowserBusy: Boolean" (DON'T FORGET TO INITIALIZE IT TO TRUE JUST PRIOR TO CALLING ".Navigate") 2) As @crefird demonstrated in his answer, use a "while" loop, only substitute "wb.Busy" for "FBrowserBusy". 3) Add an OnDocumentComplete event to your TWebBrowser instance, and have this set FBusy := False;
This will eliminate any collision, and ensure that the TWebBrowser object has completed loading the document before your outer routine proceeds to interrogate it.
Hope you find this helpful!
Please remember that OnDocumentComplete can fire multiple times (frames) when navigating a page.
How to properly implement OnDocumentComplete:
source:
http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_events.htm#OnDocumentComplete