|
|
|
|
- Overview
- Principle
- Implementation
- Example
- Parallel tasks for run the long process
- Calling RequestRefreshUI
- "Request for refreshing the display" event
- Browser timer
- Disabling the timer
- Alternative approach
Page in Session mode: Populating controls after a long process
In a web application, you may need to run long processes (for example, to update counters in a dashboard). This page explains how to run these processes: - without blocking the user interface,
- by automatically updating the data displayed when new values are available.
To populate controls with the results of long processes without blocking the browser, there's a reliable and relatively simple solution: - Use secure threads or parallel tasks to prepare the results in global variables,
- Call the WLanguage RequestRefreshUI function from the threads or parallel tasks when the results are available,
- Write the code to update the controls in the "Request for refreshing the display" event,
- Set up a browser timer that calls an asynchronous AJAX server procedure to update the controls and refresh the UI every 10 seconds or every minute, for example,
- Enable/Disable the timer as needed to avoid unnecessary AJAX calls.
Example Let's use the following example to go through the different steps: - a page containing an Dashboard control
- the new counter values are calculated in a local procedure named UpdateKIP.
- the code that starts dashboard update is written in the "Update (asynchronous)" Button control.
Parallel tasks for run the long process In the server code of the Button control, the execution of the UpdateKIP procedure is launched in a parallel task. This means that the UI is not blocked and remains responsive.. For example:
gUpdateParallelTask is ParallelTask
gUpdateParallelTask = ParallelTaskExecute(UpdateKIP, ())
In this code, a reference to the parallel task is stored in the gUpdateParallelTask global variable. To avoid launching several recalculation tasks at the same time, the Button control code checks the State property of the ParallelTask variable.
IF gUpdateParallelTask.State = ptsExecutionInProgress
ToastDisplay("Request already in progress", toastShort, vaTop, haCenter, PastelGreen)
ELSE
gUpdateParallelTask = ParallelTaskExecute(UpdateKIP, ())
END
In the browser code of the Button control, a timer is also started every second to execute a browser procedure (let's call it Update_Browser).
gnUpdateTimer = Timer(Update_Browser, 1 s)
Remark: In this example, the timer procedure is called every second. It may not be necessary to execute the timer procedure so often. Feel free to adjust the update frequency. Calling RequestRefreshUI The code of the UpdateKIP procedure recalculates the counters in the dashboard. When the server variables that are global to the page are up to date, the UpdateKIP procedure calls RequestRefreshUI. This function enables WLanguage to execute the "Request for refreshing the display" event as soon as possible. The procedure ends, terminating the parallel task. The State property of the parallel task is then set to ptsCompleted. "Request for refreshing the display" event The "Request for refreshing the display" event contains the code that updates the controls. In our example:
LOOP_KIP[gnDailyTurnoverRow].ATT_KIPName = StringBuild(gsDailyTurnover, gnDailyTurnover)
LOOP_KIP[gnNumberOrdersRow].ATT_KIPName = StringBuild(gsNumberOrders, gnOrders)
Browser timer During this time, the browser timer (Update_Browser procedure in our example) regularly executes the Update_Server server procedure. This procedure is executed via an asynchronous AJAX call. Again, the purpose is to avoid blocking the UI.
AJAXExecuteAsynchronous(ajaxUpdateControls + ajaxSynchronizeServerVariables, ...
Update_Server, AfterUpdate_Browser)
This constant allows the server code to update the controls in the page. The server call will automatically update the UI. The Update_Server procedure returns only the value of gUpdateParallelTask.State. AJAXExecuteAsynchronous automatically calls a browser procedure when the server response is received.
In the example, it is the AfterUpdate_Browser procedure. Disabling the timer The AfterUpdate_Browser takes the following parameters: - the value returned by the server procedure, here gUpdateParalleTask.State. Thus, if the parallel task is completed ( ptsCompleted constant), the timer is stopped to prevent unnecessary server calls.
- an identifier for the relevant server procedure. This identifier can be very helpful if there are multiple simultaneous AJAX calls.
PROCÉDURE AfterUpdate_Browser(sTaskStatus is string, nIdentifier is int)
Alternative approach If the process takes a long time and requires a significant amount of resources on the server side, it may be worthwhile to move the process somewhere else. In that case, simply use a WEBDEV scheduled task to perform the long process at regular intervals and store the results in the database. The site will just have to display the stored results.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|