OutSystems ONE Conference 2024: A Familiar but Exciting Event
OutSystems Reactive: Boosting UX with accelerated data fetching
Reactive parallel fetching
One of the compelling features of OutSystems Reactive is its ability to fetch aggregates (and data actions) configured to be fetched at start in parallel. This concurrent data retrieval enables the application to begin rendering the screen while the aggregates are still being fetched. As soon as aggregate results are available, they are displayed on the screen, in the order in which they are returned. This approach significantly enhances the user experience by presenting a partially populated screen much earlier, fostering a more responsive and interactive experience.
Fetching on demand
While parallel fetching at start delivers a seamless user experience, it’s not always feasible to fetch aggregates in this manner. For instance, scenarios that require dynamic aggregate retrieval, such as OnParametersChanged or OnAfterfetch, may necessitate fetching on demand. In this situation, aggregates are executed sequentially. This can hinder the user experience by delaying the display of updated data, potentially leading to a less responsive and engaging application.
Consider the OnParametersChanged screen event handler depicted in Figure 1, which involves fetching three independent aggregates. Despite the asynchronous nature of aggregate fetching, they are executed sequentially. As a result, the total time required to retrieve all data is at least the sum of the individual fetch times – a significant slowdown compared to parallel fetching at start. This delayed data retrieval translates into a slower application screen build-up, potentially impacting user satisfaction.
Conditiononal fetch at start
Another instance of this undesirable behavior arises when dealing with conditional aggregate fetching at start. For example, suppose a product card block includes text and an image. In this scenario, there are two possible situations:
- The image is already present in the parent context and is passed to the card block, or
- The image is not present, and the block needs to fetch it at start.
While it’s tempting to implement this conditional fetch in OnInitialize, as shown in Figure 2, this approach is not ideal. Although the image fetch occurs in the background, other screen aggregates are delayed until OnInitialize completes. This delay can be particularly problematic for complex applications with multiple aggregates.
Parallel fetching on demand
To address these concerns and ensure a consistently responsive user experience, we can introduce parallel fetching on demand. This technique involves encapsulating aggregate refreshes within setTimeout JavaScript function calls. setTimeout initiates a separate thread in the background to execute the refresh operation after the specified timeout period. The calling client action continues immediately, enabling subsequent refreshes to commence without delay. By setting the timeout period to 0, aggregate fetching is initiated without any delay.
Implementing parallel fetching on demand involves two straightforward steps:
- Create separate client actions for each aggregate refresh. This allows us to invoke these refreshes from JavaScript nodes.
- Replace aggregate refreshes with setTimeout JavaScript nodes. At the locations where aggregates need to be refreshed, replace the refresh with the following code:
setTimeout(function () {
$actions.RefreshAggr1(); //call the refresh client action here
}, 0);
This approach transforms the OnParametersChanged action as shown in Figure 3. By initiating refreshes in parallel, the screen is updated as soon as data becomes available, significantly improving user experience.
Similarly, the OnInitialize image fetch example will also run in parallel, allowing OnInitialize to complete immediately and enabling other aggregates to be fetched without delay.
The proof
To demonstrate the effectiveness of this technique, I’ve created an animated GIF (see Figure 5), depicting the comparison between parallel and sequential aggregate fetching. It showcases a small application with a web block that loads an image in OnInitialize and three additional images at start. By clicking a button, the images can be erased and reloaded in OnParametersChanged. Two instances of the block are displayed side by side, with the left instance employing parallel fetching and the right instance using the conventional sequential approach. To accentuate the difference, the image fetch includes an additional three-second server-side delay.
As evident from the animated GIF, parallel fetching significantly enhances the user experience by enabling faster screen updates and a more responsive application. This technique proves to be an invaluable tool for optimizing user interaction and ensuring a seamless user experience in OutSystems Reactive applications.