trywrap
Version:
A utility module to handle async function errors gracefully.
207 lines (158 loc) • 5.87 kB
Markdown
# Trywrap
Trywrap is a lightweight utility module designed to simplify error handling in asynchronous functions. By wrapping functions, it provides a cleaner, more readable way to manage errors, reducing the need for repetitive `try-catch` blocks.
## Installation
To install Trywrap, use npm:
```bash
npm install trywrap
```
## Usage
Here's a basic example of how to use Trywrap. This example demonstrates handling errors with a fallback value and a global error handler:
```javascript
const trywrap = require('trywrap');
async function testFn(value) {
if (value < 0) throw new Error("Negative value");
return `Success: ${value}`;
}
async function onError({ error, methodName, args }) {
console.error(`Caught in ${methodName} with args ${JSON.stringify(args)}:`, error.message);
}
(async () => {
const result = await trywrap(testFn, [10], { onError, fallback: "Default Value" });
console.log(result); // Success: 10
const failedResult = await trywrap(testFn, [-5], { onError, fallback: "Default Value" });
console.log(failedResult); // Default Value
})();
```
## API
### `trywrap(cb, props, options)`
#### Parameters:
- **`cb`** *(Function, required)*: The async function to be executed.
- **`props`** *(Array, optional, default: `[]`)*: Arguments to pass to the function.
- **`options`** *(Object, optional)*:
- **`onError`** *(Function)*: A callback function that is called with an object containing:
- `error`: The error object.
- `methodName`: The name of the function that threw the error.
- `args`: The arguments passed to the function.
- **`fallback`** *(any)*: A value to return if an error occurs.
- **`rethrow`** *(boolean)*: If set to `true`, the error will be rethrown after calling `onError`.
## Example Use Cases
### 1. **Handling API Calls**
In this example, Trywrap is used to handle errors during API calls, providing a fallback value if the call fails:
```javascript
async function fetchData() {
throw new Error("API failed");
}
const data = await trywrap(fetchData, [], {
onError: ({ error, methodName, args }) => {
console.error(`Caught in ${methodName} with args ${JSON.stringify(args)}:`, error.message);
},
fallback: []
});
console.log(data); // []
```
### 2. **Handling Database Queries**
Trywrap can also be used to manage errors in database queries, ensuring a fallback value is returned if an error occurs:
```javascript
async function getUser(id) {
if (id !== 1) throw new Error("User not found");
return { id, name: "John Doe" };
}
const user = await trywrap(getUser, [2], {
onError: ({ error, methodName, args }) => {
console.error(`Caught in ${methodName} with args ${JSON.stringify(args)}:`, error.message);
},
fallback: null
});
console.log(user); // null
```
### 3. **Rethrowing Errors**
This example illustrates how to rethrow errors after handling them, allowing for further error processing:
```javascript
async function riskyOperation() {
throw new Error("Something went wrong");
}
async function onError({ error, methodName, args }) {
console.error(`Caught in ${methodName} with args ${JSON.stringify(args)}:`, error.message);
}
try {
await trywrap(riskyOperation, [], { onError, rethrow: true });
} catch (err) {
console.error("Error was rethrown:", err.message);
}
```
## Traditional Nested Try-Catch vs. Trywrap
### Traditional Nested Try-Catch
Traditionally, handling errors with nested `try-catch` blocks can become cumbersome and hard to maintain:
```javascript
async function outerFunction() {
try {
// #action-1
try {
await innerFunction();
} catch (innerError) {
console.error("Inner error caught:", innerError.message);
}
// #action-2
try {
await innerFunction();
} catch (innerError) {
console.error("Inner error caught:", innerError.message);
}
// #action-3
await actionFunction();
// #action-4
await innerFunction();
} catch (outerError) {
console.error("Outer error caught:", outerError.message);
try {
await recoveryFunction();
} catch (recoveryError) {
console.error("Recovery error caught:", recoveryError.message);
}
}
}
async function actionFunction() {
return "Action function";
}
async function innerFunction() {
throw new Error("Inner function error");
}
async function recoveryFunction() {
throw new Error("Recovery function error");
}
outerFunction();
```
### Using Trywrap
With Trywrap, the same logic is simplified, reducing the need for nested `try-catch` blocks and centralizing error handling:
```javascript
async function outerFunction() {
// #action-1
await trywrap(innerFunction, [], { onError, fallback: "Fallback for action 1" });
// #action-2
await trywrap(innerFunction, []);
// #action-3
await trywrap(actionFunction, [], { onError, fallback: "Fallback for action 3" });
// #action-4
await trywrap(innerFunction, [], { onError, fallback: "Fallback for action 4" });
}
async function onError({ error, methodName }) {
console.error("Error caught in", methodName, error.message);
}
async function actionFunction() {
return "Action function";
}
async function innerFunction() {
throw new Error("Inner function error");
}
async function recoveryFunction() {
throw new Error("Recovery function error");
}
outerFunction();
```
## Why Use Trywrap?
✅ **Cleaner Code:** No more repetitive `try-catch` blocks.
✅ **Flexible:** Customize error handling with callbacks and fallbacks.
✅ **Lightweight:** Minimal overhead with just one function.
✅ **Works with Any Async Function:** Use it with API calls, database queries, file operations, etc.
## License
MIT