intentar {} sin captura {} posible en JavaScript?

114

Tengo una serie de funciones que devuelven algo o arrojan un error. En una función principal, llamo a cada uno de estos y me gustaría devolver el valor devuelto por cada función, o pasar a la segunda función si la primera función arroja un error.

Entonces, básicamente, lo que tengo actualmente es:

function testAll() {
    try { return func1(); } catch(e) {}
    try { return func2(); } catch(e) {} // If func1 throws error, try func2
    try { return func3(); } catch(e) {} // If func2 throws error, try func3
}

Pero en realidad me gustaría solo trydevolverlo (es decir, si no arroja un error). No necesito el catchbloque. Sin embargo, el código como try {}falla porque falta un catch {}bloque (sin usar) .

Pongo un ejemplo de jsFiddle .

Entonces, ¿hay alguna forma de catcheliminar esos bloques mientras se logra el mismo efecto?

pimvdb
fuente

Respuestas:

4

No. Tienes que conservarlos.

En realidad, esto tiene sentido, ya que los errores no deben ignorarse en absoluto.

ThiefMaster
fuente
16
En ese caso, esas funciones no deberían arrojar errores, sino devolver, por ejemplo, nully haces algo comoreturn func1() || func2() || func3();
ThiefMaster
52
Esta respuesta es objetivamente incorrecta, puede tenerla try {}; finally {}como se muestra en stackoverflow.com/a/5764505/68210
Daniel X Moore
4
@DanielXMoore, sin el catch (e) {}, la excepción lanzada por func1()evitaría que func2()se intente.
binki
65
A veces tiene mucho sentido tener una trampa vacía, así que no estoy de acuerdo con tu argumento.
Petr Peller
8
Esta respuesta es objetivamente incorrecta y engañosa. "Realmente tiene sentido" dices, pero estás equivocado, solo tiene sentido en algunos casos y no en otros. Es un gran ejemplo de una respuesta terrible que se acepta inexplicablemente. Hay muchos casos en los que tiene sentido no tener ningún bloque de captura, como en una asyncfunción, a veces. Ser forzado por el lenguaje javascript a crear catchbloques vacíos es claramente inútil.
YungGun
236

Un intento sin una cláusula catch envía su error al siguiente catch superior , o la ventana, si no hay ningún catch definido dentro de ese intento.

Si no tiene una captura , una expresión de prueba requiere una cláusula finalmente .

try {
    // whatever;
} finally {
    // always runs
}
Kennebec
fuente
Entonces, ¿la mejor manera sería escribir algo como try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570
1
El comentario anterior no responde con precisión a OP porque no quiere ejecutar la función 2 si la función 1 tiene éxito.
Andrew Steitz
2
Tenga en cuenta que un intento sin una captura no traga errores .
Dan Dascalescu
Gracias, eso es lo que necesitaba :-) Sería realmente increíble si también funciona sin el intento {} Quiero decir: async () => {indicarWorkInProgress () await pipelineStep1 () await pipelineStep2 () ... finalmente {stopIndicator ( )}} Estaría claro que toda la función está destinada ;-) Esos bloques de prueba son tan feos allí ...
Lenny
35

Es posible tener un bloque de captura vacío, sin una variable de error, comenzando con ES2019 . Esto se denomina enlace de captura opcional y se implementó en V8 v6.6, lanzado en junio de 2018 . La función ha estado disponible desde Node 10 , Chrome 66 , Firefox 58 , Opera 53 y Safari 11.1 .

La sintaxis se muestra a continuación:

try {
  throw new Error("This won't show anything");
} catch { };

Aún necesita un catchbloque, pero puede estar vacío y no necesita pasar ninguna variable. Si no desea ningún bloque de captura, puede usar try/ finally, pero tenga en cuenta que no se tragará errores como lo hace una captura vacía.

try {
  throw new Error("This WILL get logged");
} finally {
  console.log("This syntax does not swallow errors");
}

Dan Dascalescu
fuente
2
esta respuesta es la más actualizada! en términos de orden de ejecución, 1. intenta el trybloqueo. 2. Detecta el error. 3. Ejecuta el finallybloque. 4. Lanza el error. ¿Es esto correcto?
helsont
Gracias @helsont. En cuanto al orden de ejecución en la segunda muestra de código, no estoy seguro de que se pueda saber si el error se detecta y se vuelve a lanzar, o simplemente (probablemente) simplemente se lanza y no se detecta en primer lugar (ya que no hay catch). Rodee todo el código con otro try/catch y podrá detectar el This WILL get loggederror.
Dan Dascalescu
Parece mucho más limpio ahora. ¡Gracias por compartir!
LeOn - Han Li
10

No, catch(o finally) es tryamigo y siempre está ahí como parte de try / catch .

Sin embargo, es perfectamente válido tenerlos vacíos, como en tu ejemplo.

En los comentarios de su código de ejemplo ( si func1 arroja un error, intente con func2 ), parecería que lo que realmente quiere hacer es llamar a la siguiente función dentro del catchbloque de la anterior.

alex
fuente
1
Estás en lo correcto. Sin embargo, si un código similar try {...}; try {...}fuera posible, el significado del código podría ser más claro (pruebe el primero, de lo contrario, pruebe el segundo).
pimvdb
Acerca de su edición: en el ejemplo de JSFiddle, la segunda función devuelve algo, entonces, ¿la tercera función realmente se evalúa en ese caso? Pensé que una returndeclaración detiene cualquier cosa que venga después.
pimvdb
@pimvdb Lo siento, no revisé el violín. returnhará que la función regrese prematuramente. Actualizaré mi respuesta.
alex
1
Esta respuesta es objetivamente incorrecta, puede tenerla try {}; finally {}como se muestra en stackoverflow.com/a/5764505/68210
Daniel X Moore
1
@DanielXMoore Seguro que lo es, pero finally{}básicamente tiene el mismo espíritu que catch{}. Actualizaré la respuesta.
alex
6

No recomendaría intentar finalmente sin la captura, porque si tanto el bloque try como el bloque finalmente lanzan errores, el error arrojado en la cláusula finalmente se multiplica y el error del bloque try se ignora, en mi propia prueba:

try {
  console.log('about to error, guys!');
  throw new Error('eat me!');
} finally {
  console.log ('finally, who cares');
  throw new Error('finally error');
}

Resultado:

>     about to error, guys!
>     finally, who cares
>     .../error.js:9
>         throw new Error('finally error');
>         ^
>     
>     Error: finally error
Joe B.
fuente
1

Van juntos en todos los lenguajes que conozco que los tienen (JavaScript, Java, C #, C ++). No lo hagas.

duffymo
fuente
1
Es extraño que la mía haya sido rechazada cinco años después cuando dice lo mismo que otras respuestas aquí. El mío parece ser el único que fue votado en contra. Moderadores, tomen nota.
duffymo
Tcl tiene una construcción de una sola palabra muy convenientecatch {my code}
MKaama
¿Por qué? Se siente inútil, a menos que lo intente / finalmente.
duffymo
1

Decidí mirar el problema presentado desde un ángulo diferente.

He podido determinar una forma de permitir de cerca el patrón de código solicitado mientras, en parte, abordo el objeto de error no manejado enumerado por otro comentarista.

el código se puede ver en http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch se coloca dentro de un bucle for que permite una caída elegante. pudiendo iterar a través de todas las funciones necesarias. cuando se necesita un manejo de errores explícito, se usa una matriz de funciones adicional. en el caso de error y matriz funcional con el elemento de controladores de error no es una función, el error se descarga a la consola.

Según los requisitos de stackoverflow, aquí está el código en línea [editado para que JSLint sea compatible (elimine los espacios iniciales para confirmar), mejore la legibilidad]

function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }

// ctr = Code to Run <array>, values = values <array>, 
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
    "use strict";
    var cb; // cb = code block counter
    for (cb in ctr) {
        if (ctr.hasOwnProperty(cb)) {
            try {
                return ctr[cb](values[cb]);
            } catch (e) {
                if (typeof eh[cb] === "function") {
                    eh[cb](e);
                } else {
                    //error intentionally/accidentially ignored
                    console.log(e);
                }
            }
        }
    }
    return false;
}

window.alert(testAll([func1, func2, func3], [], []));

usuario1800957
fuente
1

Si solo desea que las funciones 2 y 3 se activen si se produce un error, ¿por qué no las pone en el bloque catch?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}
Tanque
fuente
0

Creo que necesitas usar una función auxiliar como:

function tryIt(fn, ...args) {
    try {
        return fn(...args);
    } catch {}
}

y utilícelo como:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
Itay Merchav
fuente
-2

Desde ES2019 , puede usarlo fácilmente try {}sin catch {}:

try {
  parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}

Para obtener más información, consulte la propuesta de Michael Ficcara.

JamesJGoodwin
fuente
1
No, catchtodavía se requiere, es solo la unión que no se requiere ...
chipit24