- Universal and Flexible Error Handling in ECMAScript
JavaScript's try-catch
structure is a fundamental tool for error handling, but it can be enhanced for greater flexibility and clarity. This proposal introduces the concept of allowing any block of statements, not just try
blocks, to have associated catch
blocks. Furthermore, each catch block
can have a when
clause to conditionally handle specific errors, providing a more controlled and expressive approach to managing exceptions.
Important
This proposal retains the integrity of JavaScript's control flow while offering developers a more intuitive and streamlined way to handle errors, without introducing unnecessary complexity.
{ /* ...*/ } catch (e) when (true || false) { /* ... */}
This proposal expands JavaScript’s error handling capabilities by allowing any block of statements to have its own catch
block, with the option to conditionally execute those blocks using the when
keyword. This enhancement provides developers with more control, clarity, and flexibility while maintaining compatibility with existing JavaScript syntax.
- Universal
catch
blocks: Any block of statements, including functions, loops, and even othercatch
blocks, can have its owncatch
statement. - Nested
catch
blocks: Since acatch
block is just another block of code, it can also have its owncatch
to handle errors within error-handling logic. - Conditional
catch
withwhen
: Thewhen
clause allows for conditional execution ofcatch
blocks, improving the readability and control of error handling. - Conditional catch body: If the body of the
catch
block is missing, the error variable is still available in the same scope as thecatch
block, allowing for more precise error handling.
JavaScript developers often encounter situations where they need to handle errors in specific ways based on the type of error or other conditions. The current try-catch
structure can be limiting in these scenarios, leading to complex nested conditions or multiple try-catch
blocks. By allowing catch
blocks to be attached to any block of statements, developers can handle errors more precisely and maintain a cleaner code structure.
Language as Go and Rust, allow to catch errors inline, but catch
is for control flow, and is important keep this principle. To maintain the control flow, the catch
block in this proposal is optional, and the error variable is available in the same scope as the catch block. With this proposal the following code is possible:
{ var a = 1 } catch (e);
console.log(a);
if (e) console.log(e);
In the previous example you are seeing the combination of an anonymous block
with a catch without a body
. If you want to do the same in actual JavaScript, you will need an additional block and variable:
try { var a = 1 } catch (e) { var err = e; }
console.log(a);
if (e) console.log(err);
- Precision: Handle specific error types or conditions directly.
- Clarity: The
when
clause makes the error-handling logic clear and concise. - Simplicity: Reduces the need for complex nested conditions within
catch
blocks. - Expressiveness: Offers a more powerful way to handle different error scenarios.
The proposed syntax allows for catch
blocks to be attached to any code block and for those blocks to conditionally execute based on the when
clause:
/*
any block of statements: try, anonymous, functions,
if, do, catch, finally, ...
*/
{
// Code that may throw an error
// ...
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
// catch is also a block!
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
}
finally
{
// Cleanup code, executed regardless of success or failure
// ... but finally is also a block!
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
}
catch (e);
{/* ... */ } catch when (false || true);
{ /* ... */} catch;
...
The proposed changes to the ECMAScript grammar are as follows:
14.2 Block
Syntax
Block[Yield, Await, Return] :
{ StatementList[?Yield, ?Await, ?Return] opt } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
Catch[Yield, Await, Return] :
catch ( CatchParameter[?Yield, ?Await] ) when ( Expression ) Block[?Yield, ?Await, ?Return]
catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return]
catch when ( Expression ) Block[?Yield, ?Await, ?Return]
catch Block[?Yield, ?Await, ?Return]
catch ( CatchParameter[?Yield, ?Await] )
catch
Finally[Yield, Await, Return] :
finally Block[?Yield, ?Await, ?Return]
14.15 The try Statement
Syntax
TryStatement[Yield, Await, Return] :
Block[?Yield, ?Await, ?Return]
Block: { StatementList } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
- It is a Syntax Error if
BoundNames
ofCatchParameter
contains any duplicate elements. - It is a Syntax Error if any element of the
BoundNames
ofCatchParameter
also occurs in theLexicallyDeclaredNames
ofBlock
. - It is a Syntax Error if any element of the
BoundNames
ofCatchParameter
also occurs in theVarDeclaredNames
ofBlock
. - It is a Syntax Error if the
Expression
in thewhen
clause is not a valid Boolean expression.
Catch: catch ( CatchParameter ) when ( Expression ) Block
- Let
oldEnv
be the running execution context'sLexicalEnvironment
. - Let
catchEnv
beNewDeclarativeEnvironment(oldEnv)
. - For each element
argName
of theBoundNames
ofCatchParameter
, do:- a. Perform
! catchEnv.CreateMutableBinding(argName, false)
.
- a. Perform
- Set the running execution context's
LexicalEnvironment
tocatchEnv
. - Let
status
beCompletion(BindingInitialization)
ofCatchParameter
with argumentsthrownValue
andcatchEnv
. - If
status
is an abrupt completion, then:- a. Set the running execution context's
LexicalEnvironment
tooldEnv
. - b. Return
? status
.
- a. Set the running execution context's
- If the result of evaluating
Expression
is false:- a. If there is a subsequent catch block within the same scope, continue with its evaluation.
- b. If no subsequent catch block exists, propagate the exception.
- Let
B
beCompletion(Evaluation)
ofBlock
. - Set the running execution context's
LexicalEnvironment
tooldEnv
. - Return
? B
.
Catch: catch ( CatchParameter )
- Let
oldEnv
be the running execution context'sLexicalEnvironment
. - Let
catchEnv
beNewDeclarativeEnvironment(oldEnv)
. - For each element
argName
of theBoundNames
ofCatchParameter
, do:- a. Perform
! catchEnv.CreateMutableBinding(argName, false)
.
- a. Perform
- Set the running execution context's
LexicalEnvironment
tocatchEnv
. - Let
status
beCompletion(BindingInitialization)
ofCatchParameter
with argumentsthrownValue
andcatchEnv
. - If
status
is an abrupt completion, then:- a. Set the running execution context's
LexicalEnvironment
tooldEnv
. - b. Return
? status
.
- a. Set the running execution context's
- Set the running execution context's
LexicalEnvironment
tooldEnv
. - Continue with the next statement without executing a block.
Catch: catch when ( Expression ) Block
- Let
oldEnv
be the running execution context'sLexicalEnvironment
. - Skip the environment creation since there is no
CatchParameter
. - Evaluate the
Expression
:- a. If the result of evaluating
Expression
is false:- i. If there is a subsequent catch block within the same scope, continue with its evaluation.
- ii. If no subsequent catch block exists in the current scope, propagate the exception to the next catch block in the higher scope.
- a. If the result of evaluating
- If
Expression
is true, proceed to the next statement. - Skip block evaluation since there is no block.
- Continue execution.
Catch: catch
- Let
oldEnv
be the running execution context'sLexicalEnvironment
. - Skip the environment creation since there is no
CatchParameter
. - Simply continue execution without binding any error or evaluating a block.
- Proceed to the next statement.
Block : { StatementList } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
- Let
B
beCompletion(Evaluation)
ofStatementList
. - If
B
is athrow
completion, then:- a. If a
Catch
is present, evaluateCatchClauseEvaluation
withB.[[Value]]
. - b. If
CatchClauseEvaluation
returnsundefined
, proceed to step 3. - c. Otherwise, let
C
be the result ofCatchClauseEvaluation
.
- a. If a
- If no
Catch
is present or allCatch
evaluations result inundefined
, rethrow the exception. - If a
Finally
is present, evaluate it and:- a. If the
Finally
evaluation results in an abrupt completion, return that result. - b. Otherwise, proceed with the value from the previous step.
- a. If the
- Return
? C
orB
, as appropriate.
The current try-catch
syntax is limited to the try
block, which can be followed by one or more catch
blocks and an optional finally
block. This structure is restrictive and does not allow for catch
blocks to be attached to other blocks of code.
try
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error)
{
if (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} else {
throw error;
}
}
The proposed syntax allows for catch
blocks to be attached to any block of statements, not just try
blocks. This flexibility enables developers to handle errors more precisely and conditionally, improving the readability and control of error handling.
/* any block of statements */
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error) /* optional */ when (error.message.includes("block"))
{
console.log("Caught an error in block:", error.message);
}
This proposal is compatible with the existing try-catch
syntax.
try
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error)
{
console.log("Caught an error in block:", error.message);
}
Users can conditionally handle errors based on the when
clause.
try {
data = fetchData();
}
catch (err) when (err instanceof NetworkError) {
console.error('Network error:', err.message);
}
catch (err) when (err instanceof SyntaxError) {
console.error('Syntax error in response:', err.message);
}
finally {
console.log('Cleanup code, executed regardless of success or failure.');
}
No try
block is required to have a catch
block.
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error) when (error.message.includes("block"))
{
console.log("Caught an error in block:", error.message);
}
No try
block is required to have a catch
block inside an if
statement.
if (condition) {
// ...
} catch (error) {
console.log("Caught an error in block:", error.message);
} else {
// here we are sure that there is no error in the block
console.log("No error in block.");
}
Like the previous example, but with a when
clause to conditionally handle errors.
if (condition) {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
for (let i = 0; i < 3; i++) {
throw new Error("Error in block " + i);
} catch (error) when (error.message.includes("block 1")) {
console.log("Caught an error in block 1:", error.message);
}
let i = 0;
while (i < 3) {
throw new Error("Error in block " + i);
} catch (error) when (error.message.includes("block 1")) {
console.log("Caught an error in block 1:", error.message);
i++;
}
Functions can have their own catch
blocks.
function fetchData() {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
Nested catch
blocks can handle errors within error-handling logic.
/* ... any block of statements ... */ {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
Catch exceptions must be before the while
statement.
do {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} while (false);
Catch exceptions thrown in the finally
block.
try {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} finally {
console.log("Finally block executed.");
throw new Error("Error in finally block");
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
Catch exceptions thrown in the catch
block.
try {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
throw new Error("Error in catch block");
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
Combine try-catch
with if-catch-when
inside.
try {
// ...
if (condition) {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
// enter here if error.message.includes("block") is true
// else the exception will be catched by the outer catch block
console.log("Caught an error in if block:", error.message);
}
// ...
} catch (error) {
console.log("Caught an error in try block:", error.message);
}
Catch exceptions thrown in the case
block.
switch (1) {
case 1: {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
}
// RO = risky operation
// BE = boolean expression
{ /* RO */ } catch;
{ /* RO */ } catch (e);
{ /* RO */ } catch (e) { /* ... */ }
{ /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
{ /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
{ /* RO */ } catch when ( /* BE */ );
{ /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
{ /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
{ /* RO */ } catch (e) when ( /* BE */ );
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
if ( /* BE */ ) { /* RO */ } catch;
if ( /* BE */ ) { /* RO */ } catch (e);
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ );
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ );
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch;
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e);
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ }
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch when ( /* BE */ );
/* ... */
for ( /* RO */ ) { /* RO */ } catch;
for ( /* RO */ ) { /* RO */ } catch (e);
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ );
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ );
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
while ( /* BE */ ) { /* RO */ } catch;
while ( /* BE */ ) { /* RO */ } catch (e);
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ );
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ );
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
do { /* RO */ } catch (e) while ( /* BE */ );
do { /* RO */ } catch (e) { /* ... */ } while ( /* BE */ )
do { /* RO */ } catch (e) when ( /* BE */) { /* ... */ } catch (e) { /* ... */ } while ( /* BE */ ) /* ... */
/* ... */
switch ( /* RO */ ) { case 1: { /* RO */ } catch; }
switch ( /* RO */ ) { case 1: { /* RO */ } catch when ( /* BE */ ) { /* ... */}
switch ( /* RO */ ) { case 1: { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } }
/* ... */
function f() { /* RO */ } catch;
function f() { /* RO */ } catch (e);
function f() { /* RO */ } catch (e) { /* ... */ }
function f() { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
function f() { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
function f() { /* RO */ } catch when ( /* BE */ );
function f() { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
function f() { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
function f() { /* RO */ } catch (e) when ( /* BE */ );
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
In JavaScript, when an exception is thrown, it is caught by the first catch block found in the hierarchy. This behavior remains consistent with the proposed changes. If a block does not catch the exception (either because it lacks a catch block or because the when condition evaluates to false), the exception will propagate up the call stack, where it can be caught by a higher-level catch block.
This ensures that the traditional flow of exception handling is preserved. The flexibility introduced by allowing any block to have a catch block (and potentially a when
condition) simply extends this existing mechanism, giving developers more control over how and where exceptions are handled, without altering the fundamental principles of exception propagation.
While some proposals seek to move away from the traditional try-catch
structure, often resorting to if
statements or introducing new operators, this proposal embraces and expands upon the existing use of braces {}
to maintain consistency with the current JavaScript syntax and control flow structures.
Braces {}
are a fundamental part of JavaScript's syntax, serving as the primary means to define code blocks. By leveraging this familiar structure, the proposal ensures that developers can manage errors within the same framework they use for other control flows like if
, for
, and while
loops.
Semi-colons ;
are also a fundamental part of JavaScript's syntax, serving as the primary means to separate statements. In this proposal, is recommended to use semi-colons to separate statements, but is not mandatory. For example:
{ throw new Error("Error in block") } catch
(1 + 1)
The previous code is valid, but is recommended to use semi-colons to separate statements, because the interpreter doesn't know if ( 1 + 1)
is part of the catch
block or not. Then, the following code is recommended:
{ throw new Error("Error in block") } catch; // <-- semicolon
(1 + 1)
At its core, error handling is about controlling the flow of execution in the presence of unexpected conditions. By expanding the capabilities of blocks with optional catch
and finally
clauses, this proposal provides a powerful yet intuitive way to manage errors without introducing new or unfamiliar syntax. The focus remains on enhancing existing structures, ensuring that the language remains coherent and that the learning curve for developers is minimal.
Moving away from try-catch
often results in the use of if
statements or other control structures that, while functional, can lead to redundant or less expressive code. This proposal addresses error handling in a more integrated manner, allowing developers to manage exceptions within the same block structure that controls their program's logic.
Error handling is inherently about structuring your code to handle the unexpected. This proposal keeps the focus on structure by using control flow blocks, rather than introducing operators or new constructs that might disrupt the logical flow of code. By sticking with braces, we ensure that error handling remains a natural extension of the language's existing syntax and philosophy.
Important
Storing a value in memory is not the same as telling the interpreter what the next block of statements to execute is.
This proposal advocates for an evolution of JavaScript's error-handling capabilities that respects and enhances the language's foundational structures, ensuring that developers can write cleaner, more maintainable code without sacrificing familiarity or simplicity.
Currently, JavaScript lacks the ability to type or conditionally handle errors directly in catch
blocks, resulting in complex and less readable code. This proposal introduces a more precise and clear way to handle errors, inspired by similar features in languages such as C#, F#, Scala, PL/pgSQL, Ruby, BASIC, Go, and Rust, as well as real-world scenarios where more granular error handling is needed.
-
C# and F#
when
Clause: Both C# and F# provide awhen
clause in theircatch
blocks, allowing developers to handle exceptions based on specific conditions. This inspired the idea of bringing a similar conditional mechanism to JavaScript.try { // Code that may throw an error } catch (Exception ex) when (ex.Message.Contains("block")) { Console.WriteLine("Caught an error in block: " + ex.Message); }
-
Scala's Pattern Matching in
catch
: Scala's ability to use pattern matching withincatch
blocks, combined with conditional logic, influenced the design of conditionalcatch
blocks withwhen
in this proposal.try { // Code that may throw an error } catch { case ex: Exception if ex.getMessage.contains("block") => println(s"Caught an error in block: ${ex.getMessage}") }
-
PL/pgSQL's
EXCEPTION
Handling: In PL/pgSQL, the EXCEPTION section within functions allows for specific error handling based on the type of exception, providing a structured approach to managing errors in procedural code. This inspired the idea of enhancing JavaScript's error handling within blocks and functions.BEGIN -- Code that may throw an error EXCEPTION WHEN OTHERS THEN -- Error-handling logic END;
-
BASIC's
On Error
Statement: TheOn Error
mechanism in BASIC languages like Visual Basic offers a way to direct the flow of control when an error occurs, similar to the concept of catch blocks. This inspired the proposal to allow more flexible and conditional error handling in JavaScript.On Error Goto ErrorHandler ' Code that may throw an error Exit Sub ErrorHandler: ' Error-handling logic
-
Ruby's
rescue
with Conditions: Ruby's elegant error-handling usingrescue
, which can include conditional logic within the block, inspired the flexibility and readability goals of this proposal.begin # Code that may throw an error rescue => e puts "Caught an error: #{e.message}" if e.message.include?("block") end
-
Go an Rust: Go and Rust allow to catch errors inline, but
catch
is for control flow, and is important keep this principle. To maintain the control flow, thecatch
block in this proposal is optional, and the error variable is available in the same scope as the catch block.// Go if num, err := strconv.Atoi("123a"); err != nil { fmt.Println("Error:", err) } else { fmt.Println("Number:", num) }
// Rust let num = "123a".parse::<i32>(); if let Err(e) = num { println!("Error: {}", e); } else { println!("Number: {}", num.unwrap()); }
-
Real-World Scenarios: The need for more granular control over error handling in complex JavaScript applications highlighted the limitations of the current
try-catch
structure and motivated the development of this more flexible approach.
By synthesizing these ideas and experiences from various languages and systems, this proposal aims to provide a more powerful and flexible approach to error handling in JavaScript, while maintaining the simplicity and dynamism that the language is known for.
-
Crockford, Douglas. JavaScript: The Good Parts. O'Reilly Media, 2008. ISBN: 978-0596517748.
-
Simpson, Kyle. You Don't Know JS: Scope & Closures. O'Reilly Media, 2014. ISBN: 978-1449335588.
-
Hunt, Andrew, and David Thomas. The Pragmatic Programmer: Your Journey to Mastery. Addison-Wesley Professional, 1999. ISBN: 978-0201616224.
-
Scott, Michael L. Programming Language Pragmatics. Morgan Kaufmann, 2009. ISBN: 978-0123745149.
-
McConnell, Steve. Code Complete: A Practical Handbook of Software Construction. Microsoft Press, 2004. ISBN: 978-0735619678.
-
Flanagan, David. JavaScript: The Definitive Guide. O'Reilly Media, 2020. ISBN: 978-1491952023.
-
W3Schools. "JavaScript Errors - Throw and Try to Catch". https://www.w3schools.com/js/js_errors.asp
-
Mozilla Developer Network. "Error". https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
-
Microsoft Docs. "try-catch (C# Reference)". https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch
-
Scala Documentation. "Functional Error Handling". https://docs.scala-lang.org/scala3/book/fp-functional-error-handling.html
-
PostgreSQL Documentation. "PL/pgSQL - Error Handling". https://www.postgresql.org/docs/13/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
-
Ruby Documentation. "Exceptions". https://ruby-doc.org/core-3.0.2/doc/syntax/exceptions_rdoc.html
-
BASIC Programming Language. "On Error Statement". https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/on-error-statement
-
The Go Programming Language. "Error Handling". https://golang.org/doc/effective_go#errors
-
The Rust Programming Language. "Error Handling". https://doc.rust-lang.org/book/ch09-00-error-handling.html
-
JavaScript Standard ECMA-262. https://tc39.es/ecma262
Rafael Rodríguez Ramírez
This proposal is licensed under the MIT License.