Forem

Cover image for Simplifying API Promise Handling in Next.js 15
Saiful Islam
Saiful Islam

Posted on

Simplifying API Promise Handling in Next.js 15

In modern Next.js 15 applications, API routes often deal with asynchronous operations like database queries, authentication, and data fetching. Handling these properly requires structured error management to avoid unexpected crashes.

In our previous blogs, we built:

  • A structured API response helper → serverResponse Read here
  • A request body parser → getJsonBodyData Read here

Now, we’ll take it one step further by creating a universal API promise resolver to eliminate try-catch repetition across all API routes.


Why Use a Promise Resolver for API Routes?

❌ Without it, every API function needs a try-catch block, leading to redundant code.
❌ Error handling becomes inconsistent, making debugging harder.
❌ Missed edge cases might cause APIs to crash unexpectedly.

✅ With a reusable promise resolver, we centralize error handling, reduce boilerplate, and ensure clean API code.


Building the serverAsyncResolve Helper in Next.js 15

Step 1: Creating the Promise Resolver Function

Let’s build a universal try-catch wrapper for Next.js 15 API routes:

import type { NextResponse } from "next/server";
import serverResponse from "@/helpers/server-helper/serverResponse";
import type { ServerResponseType } from "@/types";

export default async function serverAsyncResolve<T>(
  asyncCallback: () => Promise<NextResponse<ServerResponseType<T>>>,
): Promise<NextResponse<ServerResponseType<T>>> {
  try {
    return await asyncCallback();
  } catch (err) {
    if (err instanceof Error) {
      switch (err.name) {
        default:
          return serverResponse({
            success: false,
            error: err.message,
            status: 500,
          });
      }
    }
    return serverResponse({
      success: false,
      error: "Something went wrong",
      status: 500,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

🔹 This function wraps API logic inside a single async callback.
🔹 All errors are handled centrally, avoiding redundant try-catch blocks in multiple APIs.


Step 2: Using serverAsyncResolve in an API Route

Here’s an example of how to use it in a PUT request handler:

export async function PUT(req: Request) {
  return serverAsyncResolve(async () => {
    const body = await getJsonBodyData<LoginSchemaType>(req);

    return serverResponse({
      success: true,
      message: "Login successful",
      status: 200,
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

📌 Key Takeaways:
✔️ The API handler only focuses on business logic.
✔️ The async callback handles errors automatically.
✔️ The serverResponse function Read previous blog ensures consistent responses.


Benefits of This Approach

Reduces boilerplate – No need to write try-catch in every API route.
Improves error management – Centralized error handling ensures API stability.
Enhances readability – API functions focus only on business logic.

By combining serverResponse, getJsonBodyData, and serverAsyncResolve, we ensure that API routes in Next.js 15 are structured, readable, and maintainable.

💡 Have you used a similar pattern in your API routes? Let me know in the comments!

Top comments (2)

Collapse
 
perisicnikola37 profile image
Nikola Perišić

Good one. I have two questions.

  1. Why not use a global middleware to handle all API requests instead of wrapping each route with serverAsyncResolve?

  2. Why not include some form of error logging (e.g., Sentry, or a custom logger) inside serverAsyncResolve to gain better insights into production issues?

Collapse
 
saiful7778 profile image
Saiful Islam

Thank you for your response.

Answers:

  1. Yeah, we can use this serverAsyncResolve function in Nextjs 15 middleware. However, I have encountered some issues doing so.

  2. This is the initial code. In the future, I will update this code and add more features like logging.

I highly encourage you to contribute if you have a better solution. We can connect on LinkedIn, here is my Linkedin account