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?

Respuestas:


4

No. Tienes que conservarlos.

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


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
}

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


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");
}


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.


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

1

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


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], [], []));


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
      }
    }
  }
}

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 */);


-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.


1
No, catchtodavía se requiere, es solo la unión que no se requiere ...
chipit24
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.