2011-02-02 8 views
24

¿Cómo puede Javascript duplicar el modelo de ejecución de cuatro partes try - catch - else - finally compatible con otros idiomas?Javascript try ... catch ... else ... finalmente como Python, Java, Ruby, etc.

Un resumen claro y breve es del Python 2.5 what's new. En términos javascript:

// XXX THIS EXAMPLE IS A SYNTAX ERROR 
try { 
    // Protected-block 
} catch(e) { 
    // Handler-block 
} else { 
    // Else-block 
} finally { 
    // Final-block 
} 

Se ejecuta el código en Protegidas por el bloque de. Si el código arroja una excepción, se ejecuta Handler-block; Si no se lanza ninguna excepción, se ejecuta Else-block.

No importa lo que sucedió anteriormente, El bloque final se ejecuta una vez que se completa el bloque de código y se manejan las excepciones lanzadas. Incluso si hay un error en Controlador-bloque o Else-block y se genera una nueva excepción, el código en Final-block se sigue ejecutando.

Tenga en cuenta que el corte bloque else y pegar al final de Protegidas por el bloque de es equivocada. Si ocurre un error en Else-block, no debe ser manejado por Handler-block.

Respuesta

20

La extensión de la idea de jhs un poco, todo el concepto podría ser puesto dentro de una función, para proporcionar aún más la legibilidad:

var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) { 
    try { 
    var success = true; 
    try { 
     protected_code(); 
    } catch(e) { 
     success = false; 
     handler_code({"exception_was": e}); 
    } 
    if(success) { 
     else_code(); 
    } 
    } finally { 
    finally_code(); 
    } 
}; 

Entonces podemos utilizar de esta manera (muy similar a la forma de pitón):

try_catch_else_finally(function() { 
    // protected block 
}, function() { 
    // handler block 
}, function() { 
    // else block 
}, function() { 
    // final-block 
}); 
+0

Totally. Estaba pensando en hacer un módulo rápido de NPM para hacer esto. Dejé esto fuera de mi respuesta porque tienes que tener cuidado ya que el valor 'this' cambiará frente al simple 'intento' anidado. Sin embargo, mi segundo ejemplo también tiene ese error. – JasonSmith

+0

Derecha. Probablemente deseamos vincular el 'this' de la persona que llama a las cuatro devoluciones de llamada. Vamos a llamarlo un ejercicio para el lector;) – Jakob

+0

Acabo de volver a cruzar esto. Tenga en cuenta que, en las versiones más nuevas de JavaScript, la notación "flecha grasa" hace que la sintaxis sea aún más legible. – JasonSmith

7

JavaScript no tiene la sintaxis para admitir el escenario de no excepción. La mejor solución es anidado try declaraciones, similar a la técnica de "legado" de PEP 341

// A pretty-good try/catch/else/finally implementation. 
try { 
    var success = true; 
    try { 
    protected_code(); 
    } catch(e) { 
    success = false; 
    handler_code({"exception_was": e}); 
    } 
    if(success) { 
    else_code(); 
    } 
} finally { 
    this_always_runs(); 
} 

Además de facilitar la lectura, el único problema es la variable success. Si protected_code establece window.success = false, esto no funcionará. Una forma menos legible pero más seguro utiliza una función de espacio de nombres:

// A try/catch/else/finally implementation without changing variable bindings. 
try { 
    (function() { 
    var success = true; 
    try { 
     protected_code(); 
    } catch(e) { 
     success = false; 
     handler_code({"exception_was": e}); 
    } 
    if(success) { 
     else_code(); 
    } 
    })(); 
} finally { 
    this_always_runs(); 
} 
+0

para el primer ejemplo - siempre se puede utilizar new Boolean() verdadero/falso en lugar de éxito = falso | true - new Boolean() crea un objeto booleano que, cuando se compara con la existencia devuelve verdadero en contradicción con literal falsa que cuando se verifica su existencia, se devuelve falso –

21

sé que esto es viejo, pero aquí es una solución pura sintaxis , whic h Creo que es la forma correcta de ir:

try { 
    // Protected-block 
    try { 
     // Else-block 
    } catch (e) { 
     // Else-handler-block 
    } 
} catch(e) { 
    // Handler-block 
} finally { 
    // Final-block 
} 

Se ejecuta el código en Protegidas por el bloque de. Si el código arroja un error, se ejecuta Bloque manipulador; Si no se produce ningún error, se ejecuta Else-block.

No importa lo que sucedió anteriormente, El bloque final se ejecuta una vez que se completa el bloque de código y se maneja cualquier error lanzado.Incluso si hay un error en Controlador-bloque o Else-block, el código en Final-block se sigue ejecutando.

Si se emite un error en el bloque else es no manejado por el Handler-bloque pero no por el Else-manejador de bloque

Y si usted sabe que la bloque else no va a tirar:

try { 
    // Protected-block 
    // Else-block 
} catch(e) { 
    // Handler-block 
} finally { 
    // Final-block 
} 

Moraleja de la historia, que no tenga miedo a sangrar;)

+0

Agradable y limpio, sin incurrir en complejidades o dependencias adicionales. Me gusta esta solución. –

+1

Mucho mejor que agregar una variable de 'éxito' ... a menos que desee que los errores generados en el bloque 'else' salten y que el bloque de controlador principal no capte _not_, que es lo que permite la sintaxis de Python. Si eso es lo que necesita, no veo ninguna forma sin algún tipo de variable de "éxito". – doctaphred

+1

Genial. Hice esta parte de http://www.transcrypt.org. –

4

Sé que la pregunta es antigua y las respuestas ya han dado, pero creo que mi respuesta es la más simple para obtener un "else" en javascripts try-catch-block.

var error = null; 
try { 
    /*Protected-block*/ 
} catch (catchedError) { 
    error = catchedError; //necessary to make it available in finally-block 
} finally { 
    if (error) { 
     /*Handler-block*/ 
     /*e.g. console.log('error: ' + error.message);*/ 
    } else { 
     /*Else-block*/ 
    } 
    /*Final-block*/ 
}