Defining a Basic Saga in JavaScript for User Registration

Show how to implement a basic saga in JavaScript for a user registration process, involving creating a user, sending a confirmation email, and logging the action.
async function createUser(userData) {
  // Simulate user creation in a database
  console.log('Creating user...');
  return new Promise(resolve => setTimeout(() => resolve({ userId: 1, ...userData }), 1000));
This function simulates creating a user in a database, returning a promise that resolves with the user's data.
async function sendConfirmationEmail(user) {
  // Simulate sending a confirmation email
  console.log(`Sending confirmation email to ${}...`);
  return new Promise(resolve => setTimeout(() => resolve('Email sent successfully'), 1000));
This function simulates sending a confirmation email to the user, returning a promise that resolves once the email is 'sent'.
async function logAction(action) {
  // Simulate logging an action to some logging service
  console.log(`Logging action: ${action}...`);
  return new Promise(resolve => setTimeout(() => resolve('Action logged successfully'), 500));
This function simulates logging an action to a logging service, returning a promise that resolves once the action is 'logged'.
async function userRegistrationSaga(userData) {
  try {
    const user = await createUser(userData);
    await sendConfirmationEmail(user);
    await logAction(`User ${user.userId} registration completed`);
    console.log('User registration saga completed successfully');
  } catch (error) {
    console.error('Saga failed:', error);
    // Implement necessary rollback or compensating transactions here
This function orchestrates the user registration saga, chaining the creation of a user, sending a confirmation email, and logging the action together. If an error occurs, it catches it and rolls back or compensates for previous actions.