When developing an app, you may run into a case where you need to wait for a long running process to complete. A common pattern for dealing with such a case is polling. In this pattern data is repeatedly requested from a source, such an an API, at intervals. Usually, polling continues until the long running process is completed or cancelled.
For this tutorial we will consider the use case of ordering a pizza. Many pizza delivery sites now offer order tracking which update you on the progress of pizza from order submission to the moment it is delivered at your door. This tutorial uses a very simplified version of this process to show how you can use a polling pattern with Redux Sagas to update your user interface as the order progresses.
You can download the sample project for this demo from https://github.com/supertorio/redux-sagas-polling-tutorial
Note: the sample project was set up using CRA with a template for Typescript + Redux-toolkit, but you could just as easily accomplish this without typescript and using basic redux. I assume you already have familiarity with using redux and sagas and won’t be covering any project setup.
Breaking the Problem Down
When the user clicks the submit order button, we expect that an action is dispatched with a connected saga side effect. Inside that initial saga:
// 1. The order is submitted to an api and receives back an order number and the initial order status.
// 2. The store is updated with the new information.
// 3. Call pizzaStatusWatchWorker saga to begin polling
The polling watch worker saga (pizzaStatusWatchWorker) utilises the racing effects concept. This allows for the start of two simultaneous processes. When one process is completed, the other is automatically cancelled. For this race we need to:
// 4. Trigger a call effect called ‘task’ to start a polling task. The pizzaStatusPollingWorker saga runs as an infinite loop, so it will never finish before the other process.
// 5. Start a take effect called ‘cancel’ which waits and looks for the cancel action to be dispatched.
Finally in the pizzaStatusPollingWorker, is where the work of getting the next status and updating the store at an interval is accomplished
// 6. The contents are wrapped in a while statement that should run indefinitely
// 7. Fetch the new status from the API using the current order number
// 8. Update the store with new status
// 9. Check if a status is encountered that triggers an end to the polling
// 10. Dispatch the cancel action if the polling is done
// 11. Delay before the next polling iteration
These three sagas work together to provide a clean and testable way to achieve the polling pattern in your redux app.
As you can see, with a couple built in saga effects, its easy and straightforward to implement a polling pattern in your redux-sagas app. You can extend this technique further to solve for a wide variety of use cases where keeping your client app and server in sync is critical.