Blog>
Snippets

Optimistic UI Updates and Conflict Resolution

Example of implementing optimistic UI updates in an Angular app to provide immediate feedback for user actions while offline, followed by conflict resolution when reconnecting.
this.isOffline = false; // Initially, the user is assumed to be online

// Simulate a user action that changes data (e.g., updating a task)
updateTask(task) {
  // Save the original state in case we need to revert
  const originalTask = { ...task };

  // Optimistically update the UI
  this.optimisticUpdate(task);

  // Attempt to update the server
  this.taskService.update(task).subscribe(
    response => {
      // Handle the success response
      console.log('Task updated successfully on server', response);
    },
    error => {
      if (!this.isOffline) {
        // If the error is because we are offline
        this.isOffline = true;
        console.log('You are offline. Changes will be synced once you are back online.');
      }

      // If there is another problem, revert to the original state
      this.optimisticRevert(originalTask);
    }
  );
}
When a task is updated, this function optimistically assumes the update succeeds, updates the UI immediately, and then attempts to sync with the server. If the server call fails, it checks if the user is offline. If the user is offline, it logs a message; if there's another problem, it reverts the task to its original state.
// Function to optimistically update the UI
optimisticUpdate(updatedTask) {
  // Update UI elements or data here
  // This is where the Angular binding would update the task in the view
  console.log('Task optimistically updated in the UI', updatedTask);
}
This function is called to optimistically update the UI with the new task data without waiting for the server's response.
// Reverts UI changes if there's an error
optimisticRevert(originalTask) {
  // Revert the UI elements or data here
  // Restore the task in the view to its original state
  console.log('Task reverted to the original state in the UI', originalTask);
}
If the update fails and the user isn't offline due to some other error, this function reverts the UI to display the original task data before the attempted update.
// Detect when the app comes back online and attempt to sync data
window.addEventListener('online', () => {
  this.isOffline = false;
  // Sync the data when coming back online
  this.syncOfflineChanges();
});
Event listener for the window's 'online' event, which sets the offline flag to false when connectivity is restored and attempts to sync any changes made while offline.
// Sync offline changes with the server
syncOfflineChanges() {
  // Iterate over local changes that were made while offline and sync with server
  console.log('Syncing offline changes with the server...');

  // Implement actual synchronization logic here
  // This could involve sending queued requests or updating server data
  // with locally cached changes made during offline mode
}
Function called to sync all changes made while offline with the server once the connection is restored.