Cousin Glen shared a way to put the weather on our form in his blog as well as in foxite last time and so when I decided that I finally needed one because we are working simultaneously on several road construction projects these days and the weather forecast will be helpful, I did not need to look far away and simply checked what he has shared which is via XMLHttpRequest.
What is XMLHttpRequest?
XMLHttpRequest (XHR) is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPS requests to a web server and load the server response data back into the script. http://en.wikipedia.org/wiki/XMLHttpRequest
Using XMLHttpRequest has some (expected) peculiarities like it appears based on my observation that the previous request is compounding seeing my laptop which is doing the data fetching getting slower over time. Thus, I informed him of such and we decided to do these additional things:
Processing Request Lags
We are almost set to get what we need. However, another thing that we cannot remove is during when the HTTP request is being processed, thatyour unit will experience a lag which is more than a tick or two depending on the speed of your internet connection on your end. And if so, during said HTTP request you may experience a somewhat short frozen state on your app until such time the whole request process is completed and response returned back to you. And I dare say most users won't be happy with said lag.
Is there a way to avoid such then?
Avoiding Lags
There actually is no way to remove the HTTP request processing lag but we do can avoid that. Remember this? http://sandstorm36.blogspot.com.au/2012/11/run-vfp-app-like-service.html
So the trick to avoid such lags is to create another small app with, among its other jobs, is to send those HTTP requests and save the result to your local drive. Mine is set to get the info every 5 minutes. Since this app is running on another thread of its own, then your main app won't be bothered by such request lags and all you need to do later is to fetch the data from the text file it generates/updates continuously.
Service Application
I called this as service application because it does service the needs of my main ERP app like performing compressed backup, cleaning, and other things on a specified time. Now I added the XMLHttpRequest and so I will show here the portion that deals with that:
What is XMLHttpRequest?
XMLHttpRequest (XHR) is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPS requests to a web server and load the server response data back into the script. http://en.wikipedia.org/wiki/XMLHttpRequest
Using XMLHttpRequest has some (expected) peculiarities like it appears based on my observation that the previous request is compounding seeing my laptop which is doing the data fetching getting slower over time. Thus, I informed him of such and we decided to do these additional things:
- Checking Current State of the Request. Well, it is also better to perform a check to know the current state of the request operation via XMLHttpRequest's ReadyState property. Its value would be 4 when all the data has been received.
- Release the current request via XMLHttpRequest's abort method after transferring ResponseText value.
- Clearing Cache - If you don't clear the cache after the processing of the request, chances are you'll get the same result over and over again. Glen gave me another Function called DeleteUrlCacheEntryto fix that.
Processing Request Lags
We are almost set to get what we need. However, another thing that we cannot remove is during when the HTTP request is being processed, thatyour unit will experience a lag which is more than a tick or two depending on the speed of your internet connection on your end. And if so, during said HTTP request you may experience a somewhat short frozen state on your app until such time the whole request process is completed and response returned back to you. And I dare say most users won't be happy with said lag.
Is there a way to avoid such then?
Avoiding Lags
There actually is no way to remove the HTTP request processing lag but we do can avoid that. Remember this? http://sandstorm36.blogspot.com.au/2012/11/run-vfp-app-like-service.html
So the trick to avoid such lags is to create another small app with, among its other jobs, is to send those HTTP requests and save the result to your local drive. Mine is set to get the info every 5 minutes. Since this app is running on another thread of its own, then your main app won't be bothered by such request lags and all you need to do later is to fetch the data from the text file it generates/updates continuously.
Service Application
I called this as service application because it does service the needs of my main ERP app like performing compressed backup, cleaning, and other things on a specified time. Now I added the XMLHttpRequest and so I will show here the portion that deals with that:
***************
bcService.prg
***************
*For reducing memory eaten by the process
Declare Integer SetProcessWorkingSetSize In kernel32 As SetProcessWorkingSetSize ;
Integer hProcess , ;
Integer dwMinimumWorkingSetSize , ;
Integer dwMaximumWorkingSetSize
Declare Integer GetCurrentProcess In kernel32 As GetCurrentProcess
* For Clearing URL Cache
Declare Integer DeleteUrlCacheEntry In wininet String lpszUrlName
On Error Wait Window ''Nowait
Set Classlib To Addbs(Home(2))+'Solution\Toledo\systray.vcx'
Local loSysTray, loTimer
loSysTray = Createobject('myTray', 'systray.vcx')
loSysTray.AddIconToSystray()
*** Add the needed properties
Private oServices
oServices = Createobject('EMPTY')
AddProperty(oServices,'Folder',Addbs(Justpath(Sys(16,0))))
AddProperty(oServices,'GetURLCounter',0) && So it will run outright the first run
AddProperty(oServices,'GetURLSet',300) && 5 minutes interval
Set Default To (Fullpath(oServices.FolderData))
loTimer = Createobject( "myTimer" )
Read Events
Define Class myTray As systray
IconFile = Addbs(Justpath(Sys(16,0)))+"bcservice.ico"
* Use Double-click to exit service
Function iconDblClickEvent
If Messagebox('Do you really want to stop this service?',4+32,'Oooppppssss!') = 6
Clear Events
Endif
Endfunc
Enddefine
Define Class myTimer As Timer
Interval = 1000
Function Timer
* Get URL Requests based on parameter passed or default value
oServices.GetURLCounter = oServices.GetURLCounter - 1
If oServices.GetURLCounter <= 0
Local o As msxml2.xmlhttp, lcURL, lnloop, lcHTMLText, lcWord
lcHTMLText = 'Weather,PGKPHP,USDPHP,PGKINR,USDINR,PGKIDR,USDIDR,PGKUSD'
For lnloop = 1 To 8
lcWord = Getwordnum(m.lcHTMLText,m.lnloop,',')
If m.lnloop = 1
lcURL = [http://www.accuweather.com/en/pg/lae/258839/hourly-weather-forecast/258839]
Else
lcURL = [http://www.xe.com/currencyconverter/convert/?Amount=1&From=]+;
LEFT(m.lcWord,3)+[&To=]+Right(m.lcWord,3)
Endif
o = Createobject("msxml2.xmlhttp")
o.Open("GET",m.lcURL,.F.)
o.Send(.Null.)
Do While o.readyState <> 4 && Check if all data is received
ENDDO
If !Empty(o.responseText)
Try
lcFile = Addbs(oServices.Folder)+m.lcWord
Strtofile(o.responseText,m.lcFile,0)
Wait Window 'Update of '+m.lcWord+' Complete....'Nowait
Catch
Endtry
Endif
* Clean up
o.abort
o = Null
DeleteUrlCacheEntry(m.lcURL)
Next
oServices.GetURLCounter = oServices.GetURLSet
ENDIF
***** Perform other more tasks
* Reduce Memory
SetProcessWorkingSetSize(GetCurrentProcess(),-1,-1)
Endfunc
Enddefine
************ End
Now, why in the heck did I named this post localized data?
That is because my main app is actually working on files stored locally on my unit, never caring for the info coming from web or the lag it creates as the other (service) app takes care of that need. And in this way, there is absolutely no lag on updating the latest data on my main ERP app and further disseminating those information across the LAN for my other users to see.
Another reason why I decided to name this as localized data is because of the way I implemented my weather forecast widget. The animated weather showing the current hour's weather forecast do not come from the web on every change of the weather. Those are originally from the web which I downloaded and stored onto a table (not much records and won't change so I store in a table). Then I fetch a set via an SQL SELECT based on the current weather and pick one randomly to be shown on my form.
Said animated weather image changes every 60 seconds in coordination with the current weather forecast, and the information changes as well based on whether an update has already been made by the service app.
Said animated weather image changes every 60 seconds in coordination with the current weather forecast, and the information changes as well based on whether an update has already been made by the service app.
Here is my BizCore ERP app's main screen/form:
Recap:
- Create a separate app running on its own process to get the data from the web
- Use the downloaded files to update your main app
I hope this gives others some ideas.
Cheers