Lodash _.attempt: Handle Errors Without Try-Catch
The Lodash _.attempt method provides a clean, functional
approach to executing code that might throw errors without requiring
explicit try...catch blocks in your application logic. By
abstracting exception handling into a single function call, it captures
any thrown exceptions and returns either the function's result or the
caught Error object. This guide explains how
_.attempt works under the hood, how to validate its output,
and how to effectively use it in JavaScript applications.
How _.attempt Works
In standard JavaScript, code prone to runtime exceptions—such as
parsing untrusted JSON or accessing deeply dynamic operations—must be
wrapped in a try...catch block. This often leads to verbose
and deeply nested code.
The _.attempt function solves this by encapsulating the
try...catch logic internally. When you pass a function to
_.attempt, it performs the following sequence:
- Wraps the invocation of the provided function within its own
internal
tryblock. - Applies any supplied arguments to the target function.
- Returns the resulting value if execution succeeds.
- Catches any exception thrown during execution and returns that
Errorobject directly instead of letting it bubble up and crash the runtime.
Syntax and Usage
The syntax for _.attempt accepts a function followed by
any arguments to be passed to that function:
_.attempt(func, [args])A common use case is parsing JSON data, which natively throws a
SyntaxError when given malformed input:
const _ = require('lodash');
// Valid JSON
const validData = _.attempt(JSON.parse, '{"name": "Alice"}');
console.log(validData); // Output: { name: 'Alice' }
// Invalid JSON
const invalidData = _.attempt(JSON.parse, '{invalid_json}');
console.log(invalidData); // Output: [SyntaxError: Unexpected token i in JSON at position 1]Inspecting the Return
Value with _.isError
Because _.attempt returns either the successful output
or an instance of an error, you must inspect the returned value to
determine if the operation succeeded. Lodash provides the
_.isError utility specifically for this check:
const result = _.attempt(JSON.parse, rawInput);
if (_.isError(result)) {
console.error('Failed to parse input:', result.message);
} else {
console.log('Successfully parsed data:', result);
}This pattern mirrors error-handling conventions found in languages like Go, where errors are treated as normal values rather than disrupted control flows.
Synchronous Execution Limitation
It is important to note that _.attempt only intercepts
synchronous errors. It cannot catch unhandled promise rejections or
errors occurring inside asynchronous callbacks:
// This will NOT catch errors inside the Promise
const asyncResult = _.attempt(async () => {
throw new Error('Async failure');
});
// asyncResult will be a rejected Promise, not an Error objectFor asynchronous operations, native
Promise.prototype.catch() or async/await with
traditional handling must be used instead.