首頁 >web前端 >js教程 >使用 Hono RPC 實現優雅的錯誤處理和端到端類型安全

使用 Hono RPC 實現優雅的錯誤處理和端到端類型安全

Barbara Streisand
Barbara Streisand原創
2024-12-25 11:18:11856瀏覽

Elegant Error Handling and End to End typesafety with Hono RPC

我對 JavaScript 的錯誤處理一直是又愛又恨。它對 try-catch 區塊和拋出異常的依賴可能對其他人有用,但有時確實讓我感到沮喪。

考慮這個典型的 JavaScript 錯誤處理模式:

async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Error fetching data:", error.message);
  }
}

程式碼太多,但我們仍然不知道錯誤的類型。

我的觀點是,在處理錯誤時,你要知道錯誤是由什麼引起的,錯誤從哪裡來,是什麼類型的錯誤,並立即處理。特別是當您處於伺服器環境時。 對我來說


golang方式

我更喜歡像 golang 處理錯誤那樣處理錯誤,基本上將錯誤視為值。

data, err := getData()
if err != nil {
  // handle error
}

這樣您就可以立即處理錯誤,並且不必擔心出現錯誤時運行的其餘程式碼。

Supabase 使用他們的 supabase-js 函式庫做了同樣的事情。

const { data, error } = await supabase.from("users").select("*");
if (error) {
  // handle error
}

使用 Hono RPC 進行優雅的錯誤處理

我們來談談節目的主要明星

const onSubmit = async (data: SignUpSchema) => {
  const res = await callRpc(api.auth.signup.$post({ json: data }));

  if (res.error) {
    toast.error(res.error);
    return;
  }

  toast.success("Account created successfully");
  router.navigate({ to: "/" });
};

這個函數看起來可能不多,但它透過 RPC 提供型別安全的 JSON 參數。它處理所有錯誤並傳回一個包含資料或錯誤的對象,資料類型是根據端點的返回類型從 RPC 定義推斷出來的。


設定優雅的錯誤處理

使用官方文件設定Hono Rpc

設定 Hono 錯誤處理程序

後端應始終傳回包含錯誤訊息和狀態代碼的文字回應。

export const errorHandler = (err: Error | HTTPException, c: Context) => {
  console.log("=== Caught Error ===");
  if (err instanceof HTTPException) {
    return c.text(err.message, err.status);
  }
  if (err instanceof z.ZodError) {
    return c.text(err.errors.map((err) => err.message).join(",\n"), 400);
  }
  console.error(err);
  return c.text("Something went wrong", 500);
};

// Add as a errorHandler on the Hono instance
const app = new Hono();
app.onError(errorHandler);

根據 Hono 的文檔,你應該像這樣拋出 HTTPException

import { HTTPException } from "hono/http-exception";

app.post("/", async (c, next) => {
  if (somethingWentWrong) {
    throw new HTTPException(401, { message: "Custom error message" });
  }
  return c.json({ message: "Success" });
});

現在我們知道,如果發生錯誤,我們將始終收到包含錯誤訊息和狀態代碼的文字回應。


3. 在前端設定錯誤處理程序

import { ClientResponse, hc } from "hono/client";
import type { ApiRoutes } from "../../../backend/app";
const client = hc<ApiRoutes>("/");

export const callRpc = async <T>(
  rpc: Promise<ClientResponse<T>>
): Promise<{ data: T; error: null } | { data: null; error: string }> => {
  try {
    const data = await rpc;

    if (!data.ok) {
      const res = await data.text();
      return { data: null, error: res };
    }

    const res = await data.json();
    return { data: res as T, error: null };
  } catch (error) {
    return { data: null, error: (error as Error).message };
  }
};

export default client.api;

callRpc 會根據 RPC 定義自動推斷資料類型,並傳回包含資料或錯誤的物件。


4. 使用方法

從您發送的內容到您收到的內容,一切都是類型安全的

const onSubmit = async (data: SignUpSchema) => {
  const res = await callRpc(api.auth.signup.$post({ json: data }));

  if (res.error) {
    toast.error(res.error);
    return;
  }

  toast.success("Account created successfully");
  router.navigate({ to: "/" });
};

我一直在一個程式碼庫中工作,它的設定是這樣的,這是我所擁有的最流暢的開發體驗。我只是來分享的。


缺點

  • 後端僅限於傳回錯誤文字和成功回應 JSON
  • 這種模式偏離了 javascript 中處理錯誤的慣用方式
  • 你必須立即處理錯誤,這可能不是你想要的

以上是使用 Hono RPC 實現優雅的錯誤處理和端到端類型安全的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn