@solaeter/await-to-try
v0.1.0
Published
A Rust-inspired async error handling library with dual-mode distribution
Maintainers
Readme
@solaeter/await-to-try
A Rust-inspired async error handling library with dual-mode distribution
Eliminate try-catch hell and handle async errors elegantly in JavaScript/TypeScript.
Features
- Try-Catch Hell Elimination - Simplify async error handling with a clean API
- Dual-Mode Distribution - Use as an NPM library or inject source code via CLI
- Chainable Enhancements -
.toast()for error notifications and.resume()for fallback values - Highly Customizable - Inject and modify source code to fit your needs
Installation
Library Mode (NPM)
npm install @solaeter/await-to-trySource Mode (CLI)
npx solaeter-toThe CLI will guide you through:
- Selecting a template
- Choosing the destination directory (default:
./src/utils) - Injecting the source code with custom toast logic
Quick Start
Library Mode
import { _to } from '@solaeter/await-to-try';
// Handle a Promise
const { ok, result, error } = await _to(fetch('/api/data'));
if (ok) {
console.log('Data:', result);
} else {
console.error('Failed:', error);
}Source Mode
After running the CLI:
import { _to } from './utils/to';
// Same API as library mode
const { ok, result, error } = await _to(asyncOperation());API
_to(task)
Wraps a Promise or function execution result in a standardized format.
Parameters:
task:Promise<T> | (() => Promise<T>) | (() => T>- The task to handle
Returns: Promise<PromiseProxy<T>> - A promise that resolves to a result object
Result Structure:
{
ok: boolean; // true if successful, false if failed
result?: T; // the result value (when ok is true)
error?: unknown; // the error object (when ok is false)
}Usage Examples
Basic Usage
// Handle a Promise
const { ok, result, error } = await _to(Promise.resolve(42));
console.log(ok); // true
console.log(result); // 42
// Handle an async function
const { ok, result, error } = await _to(async () => {
const res = await db.query('SELECT * FROM users');
return res;
});
// Handle a sync function
const { ok, result, error } = await _to(() => {
return JSON.parse(jsonString);
});Using .toast() for Error Notifications
When an operation fails, .toast() displays an error message:
await _to(asyncOperation)
.toast('操作失败,请重试');
// Only shows toast when the operation failsCustomizing Toast Logic:
In Source Mode, edit the toast logic in the injected file:
// Example: Using Ant Design
import { message } from 'antd';
// In the toast method:
message.error(message);
// Example: Using Element UI
import { ElMessage } from 'element-plus';
// In the toast method:
ElMessage.error(message);
// Example: Using React Toastify
import { toast } from 'react-toastify';
// In the toast method:
toast.error(message);Using .resume() for Fallback Values
When an operation fails, .resume() returns a fallback value:
// Simple fallback
const data = await _to(fetchUserData())
.resume({ id: 0, name: 'Guest' });
// If fetchUserData fails, returns the guest user objectCombining .toast() and .resume()
const items = await _to(fetchItems())
.toast('列表加载失败,请检查网络')
.resume([]);
// If fetchItems() fails:
// 1. Shows toast message
// 2. Returns empty array []Advanced Examples
User Data Fetching
async function getUserProfile(userId: number) {
const { ok, result: user, error } = await _to(
fetch(`/api/users/${userId}`).then(res => res.json())
);
if (!ok) {
return null;
}
return user;
}
// Or with chaining
const user = await getUserProfile(1)
.toast('用户数据加载失败')
.resume(null);Multiple Async Operations
async function loadDashboard() {
const [users, posts, comments] = await Promise.all([
_to(fetchUsers()),
_to(fetchPosts()),
_to(fetchComments())
]);
const usersData = users[0].ok ? users[0].result : [];
const postsData = posts[0].ok ? posts[0].result : [];
const commentsData = comments[0].ok ? comments[0].result : [];
return { users: usersData, posts: postsData, comments: commentsData };
}Error Recovery
async function fetchDataWithRetry(url: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const { ok, result, error } = await _to(fetch(url));
if (ok) {
return result;
}
if (i === maxRetries - 1) {
await _to(Promise.reject(error))
.toast(`请求失败,已重试 ${maxRetries} 次`);
}
}
return null;
}CLI Usage
Interactive Mode
npx solaeter-toYou'll be prompted to:
- Choose a template (currently:
to.ts) - Specify the output directory (default:
./src/utils) - Confirm the injection
The injected file will have:
- Your project name
- Current date
- Customizable toast logic
- Full source code access
Customizing Injected Code
After injection, edit src/utils/to.ts to customize:
// Find the toast method in the file
if (prop === 'toast') {
return (message: string) => {
if (!target.ok && target.error) {
// ========================================
// Toast 逻辑 - 自定义区域
// ========================================
// Add your custom toast implementation here
showToast({ type: 'error', message });
// ========================================
}
return target;
};
}Comparison
Traditional Try-Catch
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
// Fallback handling
}Using _to
const { ok, result: data } = await _to(
fetch('/api/data').then(res => res.json())
)
.toast('数据加载失败')
.resume(null);
if (data) {
console.log(data);
}License
MIT
Author
Solaeter
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
