Introduction
JavaScript error handling is about to get a major upgrade. The new ECMAScript Safe Assignment Operator Proposal (?=
) is here to streamline your code by reducing the need for traditional try-catch
blocks. Let’s explore how this proposal can simplify your error management and make your JavaScript code cleaner and more efficient.
Simplified Error Handling
No More Nested Try-Catch
-
Problem: Traditional
try-catch
blocks often lead to deeply nested code, making it harder to read and maintain. -
Solution: The
?=
operator reduces nesting by transforming the result of a function into a tuple. If an error occurs, it returns[error, null]
; otherwise, it returns[null, result]
.
Example:
async function getData() {
const [error, response] ?= await fetch("https://api.example.com/data");
if (error) return handleError(error);
return response;
}
Enhanced Readability
Cleaner, More Linear Code
-
Problem:
Try-catch
blocks can clutter code and disrupt the flow of logic. -
Solution: The
?=
operator makes error handling more intuitive, keeping your code linear and easy to follow.
Example:
const [error, data] ?= await someAsyncFunction();
if (error) handle(error);
Consistency Across APIs
Uniform Error Handling
- Problem: Different APIs might require different error-handling techniques, leading to inconsistencies.
-
Solution: The
?=
operator introduces a consistent way to handle errors across all APIs, ensuring uniform behavior.
Improved Security
Never Miss an Error Again
- Problem: Overlooking error handling can lead to unnoticed bugs and potential security risks.
-
Solution: By automatically handling errors in a standardized way, the
?=
operator reduces the chance of missing critical errors.
Symbol.result: The Secret Sauce
Customizable Error Handling
-
Overview: Objects that implement the
Symbol.result
method can use the?=
operator to define their own error-handling logic. -
Usage: The
Symbol.result
method should return a tuple[error, result]
.
Example:
function example() {
return {
[Symbol.result]() {
return [new Error("Error message"), null];
},
};
}
const [error, result] ?= example();
Recursive Error Handling
Handle Nested Errors Like a Pro
-
Overview: The
?=
operator can recursively handle nested objects that implementSymbol.result
, ensuring even complex error scenarios are managed smoothly.
Example:
const obj = {
[Symbol.result]() {
return [
null,
{ [Symbol.result]: () => [new Error("Nested error"), null] }
];
},
};
const [error, data] ?= obj;
Promises and Async Functions
Async Error Handling Made Easy
-
Overview: The
?=
operator is designed to work seamlessly with Promises and async/await, making error handling in asynchronous code straightforward.
Example:
const [error, data] ?= await fetch("https://api.example.com");
Using Statement Integration
Streamline Resource Management
-
Overview: The
?=
operator can be used withusing
statements to manage resources more effectively, making cleanup easier and less error-prone.
Example:
await using [error, resource] ?= getResource();
Why Not Data First?
Prioritizing Error Handling
-
Overview: Placing the error first in the
[error, data] ?=
structure ensures that errors are handled before processing data, reducing the risk of ignoring errors.
Example:
const [error, data] ?= someFunction();
Polyfilling the Operator
Future-Proof Your Code
-
Overview: While the
?=
operator cannot be polyfilled directly, its behavior can be simulated using post-processors to maintain compatibility with older environments.
Example:
const [error, data] = someFunction[Symbol.result]();
Learning from Other Languages
Inspired by the Best
-
Overview: The pattern behind the
?=
operator is inspired by similar constructs in languages like Go, Rust, and Swift, which have long embraced more structured error handling.
Current Limitations and Areas for Improvement
Still a Work in Progress
-
Nomenclature: The proposal needs a clear term for objects implementing
Symbol.result
. -
Finally Blocks: There’s no new syntax for
finally
blocks, but you can still use them in the traditional way.
For more information, visit the GitHub repository.
Conclusion
The Safe Assignment Operator (?=
) is a game-changer for JavaScript error handling, promising to reduce the need for clunky try-catch
blocks and make your code cleaner and more secure. Although still in development, this proposal could soon become a standard tool in every JavaScript developer’s toolkit.
Top comments (58)
It won't be soon (if at all) - this is only a draft proposal that hasn't even been accepted for consideration yet, let alone adoption
Lol the "elephant in the room" - the article does not mention anything about where this proposal is documented, nor about its expected timeline ...
"Bye Bye, Try-Catch Blocks" - that's highly premature, to put it mildly ...
"JavaScript error handling is about to get a major upgrade" - is rather misleading ...
P.S. and if you think critically about it for a moment, then you'll probably conclude that the advertised advantages might actually be disadvantages in the context of JS ... I see more negative views of this proposal than positive ones here:
reddit.com/r/javascript/comments/1...
I'm also not really convinced ...
If you look at the syntax votes
?=
is not even the front runner.(also total votes add up to 666)
Can you link the details of the above? Wondering what try as throw means.
Here's the issue.
github.com/arthurfiorette/proposal...
Thanks! I love the lively discussion going on over there.
Beast number :D
Dang. I'm looking forward to the 101 almost-the-same-but-missing-nuanced implementations that npm packages or each framework will introduce...
If you're really adverse to the try/catch block you can make a helper function that does the same as the safe assignment operator. I really don't see it getting much traction unfortunately, especially seeing as it's such an easy function.
You don't need a callback, this can be done by simply awaiting the value (Promise object)
What you don't need is precisely
await
. Here's an example of this:This works pretty well when loading multiple stuff at the same time so you don't block the thread on every single request by awaiting the response before continuing with the next one; meaning that you can call useService in a
promise.all
orpromise.allSettled
and expect all requests to be launched at the same time, in parallel and capture the responses seamlessly (and asynchronously as -hopefully- intended).This can be used along any framework, library or with Vanilla JS if you are eager to toy around with object proxies or any other methodology you prefer. This is, though, a simplification of what I have on a Next (React) project as you may have noticed by the Dispatch type hint. Following that, an usage example would be:
We're coding in a "reactive" manner pretty much since Angular JS first came out (14 years ago 🤯), try to avoid breaking the asynchrony unless it's completely necessary; instead let things react to other things when they find suit, simply let it flow! 😎
As a bonus advice, try not to use
await
in the same instruction where athen
is present and vice-versa unless you know very well what you are doing.This is what the title example looks like with promises.
The proposal reminds me of the "nodeback" error-first callback style before the majority of the asynchronous actions adopted promises. I prefer promises, and dislike the need for try/catch blocks and
async
function declarations that come withawait
. This proposal is a better solution than try/catch blocks, but it seems to me like we're 60% of the way back to a promise chain but still with more characters and more mental parsing.someFunction().then().catch().finally();
Also, there is no need for a
finally
equivalent with Safe Assignment because we've eliminated the scoping. You can use plain conditions.Thank you for putting the article together. I appreciate the work on it, even if I don't like proposal. 😅
I agree with you but there is one thing though.
finally
block is meant to be executed regardless of whether your code succeed, get an error and handle it successfully, get an error and throw it again, or throw its own error. It is a misconception that afinally
block is equivalent to the code that follows the try-catch-else block.Instead, I suggest this modified solution.
Finally,
finally
block is used to free allocated resources or to close a file so we make sure that it is not interrupted by any event.i n d i a n c l i c k b a i t.
From the producers of unnecessary copy/pasted Medium post, comes...
it seems like javascript is learning something from GO:
golang doesn't support try-catch blocks at all.
100% FALSE and B.S.
Try-Catch is straight-forward language.
The ?= is CONFUSI(NG to begin with.
The ?= should be canned and thrown away.
It's look stupid and Go, Rust, and Swift, are not known to easy or that popular.
BUt lots of HYPE...
The ?= is just WANNBE nonsense.
It's still a draft. In the meantime you can do this:
So basically, JavaScript has found yet another way of being "kinda like Lua, except worse"?
What about this:
The title is super misleading since it makes it sound like this feature is like ECMA Stage 3 which is totally untrue. Claiming "this proposal could soon become a standard tool in every JavaScript developer’s toolkit" is very naive; just remember how much it took for Decorators to come to Stage 3, it's been an eternity.
As for the proposal itself, yes it improves error handling in some areas but to me it looks like it makes other areas worse, like bubbling up errors would become way more manual with it.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.