Basic Usage Examples
Explore basic usage examples of go-errors for synchronous, asynchronous, and API operations.
Basic Usage
This section provides fundamental examples to illustrate the basic usage of go-errors in various scenarios. These examples cover synchronous operations, asynchronous operations, handling multiple operations, and API integrations.
goSync
1. Simple Synchronous Error Handling with The goSync
function is ideal for wrapping synchronous operations that might throw errors. Here’s an example of a safeDivide
function that uses goSync
to handle potential division by zero errors:
import { goSync } from 'go-errors';
function safeDivide(a: number, b: number): [number | null, Error | null] {
let [result, err] = goSync(() => {
if (b === 0) {
throw new Error('Cannot divide by zero!');
}
return a / b;
});
if (err) {
console.error('Division operation failed:', err.message);
return [null, err]; // Return null value and the error
}
return [result, null]; // Return the result and null error
}
// Usage examples
let [successResult, successError] = safeDivide(10, 2);
if (successError) {
console.error('Error:', successError.message);
} else {
console.log('Successful division result:', successResult); // Output: Successful division result: 5
}
let [failResult, failError] = safeDivide(5, 0);
if (failError) {
console.error('Error:', failError.message); // Output: Error: Cannot divide by zero!
} else {
console.log('Division result:', failResult);
}
In this example, goSync
elegantly handles the potential error within the divide
operation, returning a Result
tuple that clearly indicates either success or failure.
go
2. Handling Asynchronous Operations with For asynchronous operations, such as fetching data from an API, the go
function is used. The following example demonstrates fetching user data using go
and goFetch
:
import { goFetch } from 'go-errors';
interface User {
id: string;
firstName: string;
lastName: string;
fullName: string;
}
async function fetchUserData(userId: string): Promise<[User | null, string | null]> {
let [user, err] = await goFetch<User>(`/api/users/${userId}`, {
responseTransformer: (data: any) => ({
...data,
fullName: `${data.firstName} ${data.lastName}` // Enhance user data
})
});
if (err) {
console.error('Failed to fetch user data:', err);
return [null, err]; // Return null user and the error
}
return [user, null]; // Return user data and null error
}
async function main() {
let [userData, fetchError] = await fetchUserData('123');
if (fetchError) {
console.error('Fetch error:', fetchError.message);
} else {
console.log('Fetched user data:', userData); // Output: User data: { id: '123', firstName: '...', lastName: '...', fullName: '...' }
}
}
main();
This example showcases how goFetch
simplifies asynchronous API calls and error handling, providing a clean and type-safe way to manage API responses.
3. Composing Multiple Operations
go-errors makes it straightforward to compose multiple operations, handling errors at each step. Consider a scenario where you need to fetch user data, validate it, and then save it to a database:
import { goSync, go, goFetch } from 'go-errors';
interface User { /* ... */ } // Assume User interface is defined
async function processUserData(userId: string): Promise<[User | null, Error | null]> {
// Fetch user data
let [user, fetchErr] = await goFetch<User>(`/api/users/${userId}`);
if (fetchErr) {
console.error('Fetch user failed:', fetchErr.message);
return [null, fetchErr];
}
// Validate user data synchronously
let [validatedUser, validationErr] = goSync(() => validateUser(user)); // Assume validateUser function exists
if (validationErr) {
console.error('User validation failed:', validationErr.message);
return [null, validationErr];
}
// Save validated user data asynchronously
let [savedUser, saveErr] = await go(saveUserToDatabase(validatedUser)); // Assume saveUserToDatabase function exists
if (saveErr) {
console.error('Save user failed:', saveErr.message);
return [null, saveErr];
}
return [savedUser, null]; // Return saved user and null error
}
async function main() {
let [processedUser, processError] = await processUserData('123');
if (processError) {
console.error('User processing error:', processError.message);
} else {
console.log('Processed user data:', processedUser); // Output: Processed user data: { ... }
}
}
main();
This example demonstrates how to chain goFetch
, goSync
, and go
to handle a sequence of operations, with error checking at each step, leading to robust and readable code.
goFetch
4. Integrating with APIs using goFetch
is particularly useful for integrating with REST APIs, providing options for response and error transformation. Here’s an example of fetching user data from an API and transforming the response:
import { goFetch } from 'go-errors';
interface ApiResponse<T> {
data: T;
metadata: { version: string };
}
interface User { /* ... */ } // Assume User interface is defined
async function fetchUserFromApi(userId: string): Promise<[User | null, string | null]> {
let [apiResponse, apiError] = await goFetch<ApiResponse<User>>(`/api/users/${userId}`, {
responseTransformer: (data: any) => {
return {
...data.data, // Extract user data from ApiResponse
fullName: `${data.data.firstName} ${data.data.lastName}` // Enhance user data
} as User;
},
errorTransformer: (error: any) => `API request failed: ${error.message || error}` // Custom error transformation
});
if (apiError) {
console.error('API request error:', apiError);
return [null, apiError];
}
return [apiResponse, null];
}
async function main() {
let [userApiResponse, apiError] = await fetchUserFromApi('123');
if (apiError) {
console.error('API Error:', apiError);
} else {
console.log('API User Response:', userApiResponse); // Output: API User Response: { data: { ... }, metadata: { ... } }
}
}
main();
This example illustrates the use of responseTransformer
and errorTransformer
in goFetch
to customize data and error handling for API interactions, making your API integration code cleaner and more maintainable.
Next Steps
These basic examples provide a foundation for using go-errors in your projects. To explore more advanced features and usage patterns, continue with these sections:
- Custom Error Types: Learn how to define and use custom error types for more specific error handling.
- Error Propagation: Understand different strategies for propagating errors in complex applications.
- API Reference: Dive deeper into the API documentation for detailed information on all functions and options.