跳到主要内容

语法糖

本文档展示如何使用 SDK 提供的 safesqlSafe 语法糖,简化错误处理代码。

版本要求
  • safe 函数需要 @lovrabet/sdk v1.3.0 及以上版本
  • sqlSafe 函数需要 @lovrabet/sdk v1.3.0 及以上版本

传统写法:繁琐且容易出错

场景一:普通 API 调用

// 📌 传统写法:两层嵌套
try {
const users = await client.models.users.filter();
console.log(users);
} catch (error) {
if (error instanceof LovrabetError) {
console.error(error.message, error.description);
} else {
console.error(error);
}
}

问题

  • try-catch 增加嵌套层级
  • 需要手动判断 error 类型
  • 代码量大,可读性差

场景二:SQL 查询

// 📌 传统写法:三层检查
try {
const result = await client.sql.execute({ sqlCode: "xxx" });

// 业务层检查
if (result.execSuccess && result.execResult) {
console.log(`查询到 ${result.execResult.length} 条记录`);
result.execResult.forEach((row) => console.log(row));
} else {
console.error("SQL 执行失败");
}
} catch (error) {
if (error instanceof LovrabetError) {
console.error("请求失败:", error.message);
}
}

问题

  • HTTP 错误 + 业务逻辑错误,两层检查
  • execResult 嵌套访问
  • 代码重复,容易遗漏检查

场景三:并发请求

// 📌 传统写法:错误处理分散
const [users, orders, stats] = await Promise.all([
client.models.users.filter().catch((e) => ({ error: e })),
client.models.orders.filter().catch((e) => ({ error: e })),
client.sql.execute({ sqlCode: "stats" }).catch((e) => ({ error: e })),
]);

if (users.error) console.error("获取用户失败");
if (orders.error) console.error("获取订单失败");
if (stats.error) {
console.error("获取统计失败");
} else {
if (!stats.data.execSuccess) {
console.error("SQL 执行失败");
}
}

问题

  • 每个请求都要单独处理错误
  • SQL 的业务状态检查更复杂
  • 代码结构不统一

使用 safe:简化普通 API 错误处理

import { safe } from "@lovrabet/sdk";

// 💡 语法糖:一次检查
const { data, error } = await safe(() => client.models.users.filter());

if (error) {
console.error("查询失败:", error.message, error.description);
return;
}

// data 直接是结果数据
console.log(data);

对比

传统safe
try-catch 嵌套平级解构
手动判断 error 类型自动转换为 LovrabetError
5-10 行代码3 行代码

并发请求:结构统一

// ✅ 简洁:统一处理
const [usersResult, ordersResult, statsResult] = await Promise.all([
safe(() => client.models.users.filter()),
safe(() => client.models.orders.filter()),
safe(() => client.sql.execute({ sqlCode: "stats" })),
]);

// 逐个检查
if (usersResult.error) console.error("用户失败");
if (ordersResult.error) console.error("订单失败");
if (statsResult.error) console.error("统计失败");

// 使用成功的数据
usersResult.data?.forEach((user) => console.log(user));

使用 sqlSafe:专为 SQL 优化

import { sqlSafe } from "@lovrabet/sdk";

// ✅ 简洁:一次检查,直接拿到数组
const { data, error } = await sqlSafe(() =>
client.sql.execute({ sqlCode: "user-stats" })
);

if (!error) {
// data 直接是查询结果数组
console.log(`查询到 ${data.length} 条记录`);
data.forEach((row) => console.log(row));
}

对比

传统sqlSafe
try-catch + execSuccess 检查一次 if 判断
访问 result.execResult直接访问 data
10-15 行代码5 行代码

带类型的 SQL 查询

interface UserStat {
id: number;
name: string;
login_count: number;
}

const { data, error } = await sqlSafe<UserStat>(() =>
client.sql.execute<UserStat>({ sqlCode: "user-stats" })
);

if (error) return;

// data 是 UserStat[],类型安全
data.forEach((stat) => {
console.log(`${stat.name}: ${stat.login_count} 次登录`);
});

语法糖对比表

场景传统写法(代码行数)语法糖(代码行数)
普通 API 错误处理8-10 行3 行
SQL 查询完整处理15-20 行5 行
并发请求30+ 行10 行
类型安全访问需要类型断言自动推断

最佳实践

1. 优先使用语法糖

// 💡 语法糖:简洁
const { data, error } = await safe(() => api.call());
if (error) return;

// 📌 传统写法:繁琐
try {
const data = await api.call();
} catch (e) {
if (e instanceof LovrabetError) {
// ...
}
}

2. SQL 必须用 sqlSafe

// 💡 语法糖:一次检查
const { data, error } = await sqlSafe(() => client.sql.execute(...));

// ❌ 避免:容易遗漏业务检查
const result = await client.sql.execute(...);
result.execResult?.forEach(...); // 可能 execSuccess=false

3. 早期返回模式

const fetchUsers = async () => {
const { data, error } = await safe(() => client.models.users.filter());
if (error) return { success: false, error: error.message };
return { success: true, data };
};

4. 并发请求统一处理

const loadDashboard = async () => {
const [users, orders, stats] = await Promise.all([
sqlSafe(() => client.sql.execute({ sqlCode: "users" })),
sqlSafe(() => client.sql.execute({ sqlCode: "orders" })),
sqlSafe(() => client.sql.execute({ sqlCode: "stats" })),
]);

if (users.error || orders.error || stats.error) {
console.error("数据加载失败");
return;
}

return {
users: users.data!,
orders: orders.data!,
stats: stats.data!,
};
};

API 参考

safe

function safe<T>(fn: Promise<T> | (() => Promise<T>)): Promise<SafeResult<T>>;

interface SafeResult<T> {
data: T | null;
error: LovrabetError | null;
}

sqlSafe

function sqlSafe<T>(
fn: Promise<SqlExecuteResult<T>> | (() => Promise<SqlExecuteResult<T>>)
): Promise<SqlSafeResult<T>>;

interface SqlSafeResult<T> {
data: T[] | null;
error: LovrabetError | null;
}

相关文档