GET Method - Global Error Handling

Why Use Global Error Handling?

Instead of handling errors in every single GET request, configure it once globally and let hmm-api handle all errors automatically.

Complete Example

import ApiClient, { parseResponseMessage } from "hmm-api";
import { toast } from "sonner";

// Configure once - handles ALL GET requests
const api = new ApiClient({
  baseUrl: "https://api.example.com",
  returnParsedError: true,
  onError: (response) => {
    // Handle ALL errors globally
    toast.error(response.error);

    if (response.status === 401) {
      redirectToLogin();
    }
  },
});

// Usage - No error handling needed!
interface User {
  id: number;
  name: string;
  email: string;
}

const UserComponent = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(false);

  const fetchUsers = async () => {
    setLoading(true);

    // Simple GET - errors handled automatically
    const response = await api.get<User[]>("/users", {
      finally: () => setLoading(false),
    });

    if (response.success) {
      setUsers(response.data);
    }
  };

  const fetchUserById = async (id: number) => {
    const response = await api.get<User>(`/users/${id}`);
    // No error handling needed - global config handles it!

    if (response.success) {
      return response.data;
    }
  };

  return (
    <div>
      <button onClick={fetchUsers} disabled={loading}>
        {loading ? "Loading..." : "Fetch Users"}
      </button>
      {/* Render users */}
    </div>
  );
};

Key Benefits

  • No repetitive error handling - Configure once, works everywhere
  • Consistent UX - All errors shown the same way
  • Clean code - Focus on data, not error handling
  • Global auth handling - 401 errors handled automatically

Advanced GET Features (v2.0.0)

Polling with GET

Perfect for checking job status, waiting for data updates, or real-time monitoring:

const checkJobStatus = async (jobId: string) => {
  const customPollId = `job-status-${jobId}`;

  const result = await api.get(`/jobs/${jobId}/status`, {
    poll: {
      interval: 2000, // Check every 2 seconds
      maxAttempts: 30, // Stop after 30 attempts
      pollId: customPollId, // Custom poll ID for this job
      stopCondition: (response) => {
        // Stop when job is complete
        return response.success && response.data.status === "completed";
      },
      onPollSuccess: (response, attempt) => {
        console.log(
          `Job ${jobId} - Attempt ${attempt}: ${response.data.progress}%`
        );
        updateProgressBar(response.data.progress);
      },
    },
  });

  // Check if it's a polling result
  if ("finalResponse" in result) {
    console.log(`Job ${jobId} completed after ${result.attempts} attempts`);
    console.log(`Poll ID: ${result.pollId}`); // Custom poll ID
    return result.finalResponse.data;
  }
};

// Cancel job status checking from anywhere in your app
const cancelJobStatusCheck = (jobId: string) => {
  const pollId = `job-status-${jobId}`;
  const stopped = api.stopPolling(pollId);

  if (stopped) {
    console.log(`Cancelled status checking for job ${jobId}`);
  }
};

Download Progress with GET

Track download progress for large files:

const downloadFile = async (fileId: string) => {
  const response = await api.get(`/files/${fileId}/download`, {
    onDownloadProgress: (progress) => {
      console.log(`Download: ${progress.percentage}%`);
      updateDownloadProgress(progress.percentage);

      // Show detailed progress
      console.log(`${progress.loaded} / ${progress.total} bytes`);
    },
    timeout: 60000, // 1 minute timeout for large files
  });

  if (response.success) {
    saveFile(response.data);
  }
};

Multiple Polling Operations

Run multiple GET polling operations simultaneously:

const Dashboard = () => {
  const [data, setData] = useState({});

  // Define poll IDs for better management
  const POLL_IDS = {
    orders: "dashboard-orders",
    inventory: "dashboard-inventory",
    system: "dashboard-system",
  };

  const startMultiplePolling = async () => {
    // Start 3 independent polling operations with custom IDs
    const [orders, inventory, system] = await Promise.all([
      api.get("/dashboard/orders", {
        poll: {
          interval: 3000,
          pollId: POLL_IDS.orders, // Custom poll ID
          onPollSuccess: (response) => {
            setData((prev) => ({ ...prev, orders: response.data }));
          },
        },
      }),

      api.get("/dashboard/inventory", {
        poll: {
          interval: 5000,
          pollId: POLL_IDS.inventory, // Custom poll ID
          onPollSuccess: (response) => {
            setData((prev) => ({ ...prev, inventory: response.data }));
          },
        },
      }),

      api.get("/dashboard/system", {
        poll: {
          interval: 2000,
          pollId: POLL_IDS.system, // Custom poll ID
          onPollSuccess: (response) => {
            setData((prev) => ({ ...prev, system: response.data }));
          },
        },
      }),
    ]);

    // Verify poll IDs
    console.log("Started polls:", {
      orders: orders.pollId,
      inventory: inventory.pollId,
      system: system.pollId,
    });
    console.log(`Active polls: ${api.getActivePollingCount()}`); // 3
  };

  const stopSpecificPolling = (type: keyof typeof POLL_IDS) => {
    const stopped = api.stopPolling(POLL_IDS[type]);
    console.log(`Stopped ${type} polling: ${stopped}`);
  };

  const stopAllPolling = () => {
    api.stopAllPolling();
    console.log(`Active polls: ${api.getActivePollingCount()}`); // 0
  };

  return (
    <div>
      <button onClick={startMultiplePolling}>Start Dashboard Polling</button>
      <button onClick={stopAllPolling}>Stop All Polling</button>
      {/* Render dashboard data */}
    </div>
  );
};

When to Override Global Handling

Only override when you need specific behavior for a particular request:

// Special case: Silent error for optional data
const response = await api.get("/optional-data", {
  showError: false, // Don't show toast for this one
  onError: (response) => {
    console.log("Optional data not available, using defaults");
    useDefaultData();
  },
});

// Special case: Custom timeout for slow endpoints
const response = await api.get("/heavy-computation", {
  timeout: 120000, // 2 minutes for heavy operations
});