try-catch en javascript ... ¿no es una buena práctica?

65

Hay una disposición para el bloque try-catch en javascript . Mientras que en java o en cualquier otro idioma es obligatorio tener un manejo de errores, no veo que nadie los use en javascript para mayor extensión. ¿No es una buena práctica o simplemente no los necesitamos en javascript?

    
pregunta akp 13.04.2012 - 18:19

6 respuestas

63

Uno debe evitar los errores throw como la forma de pasar las condiciones de error en las aplicaciones.

La declaración throw solo debe usarse "Para que esto nunca suceda, falle y queme. No se recupere elegantemente de ninguna manera"

Sin embargo,

try catch se usa en situaciones en las que los objetos del host o ECMAScript pueden generar errores.

Ejemplo:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

Las recomendaciones en la comunidad node.js es que pasa errores en las devoluciones de llamada (porque los errores solo se producen en operaciones asíncronas) como primer argumento

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

También hay otros problemas, como intentar / capturar es muy costoso y es feo y simplemente no funciona con operaciones asíncronas.

Por lo tanto, dado que las operaciones síncronas no deberían generar un error y no funcionan con operaciones asíncronas, nadie usa el método catch catch, excepto los errores generados por los objetos del host o ECMAScript

    
respondido por el Raynos 13.04.2012 - 18:30
32

Try / catch en Javascript no es tan a prueba de balas como en otros idiomas, debido a la naturaleza asíncrona de Javascript. Considera este fragmento:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

El problema es que el flujo de control deja el bloque try antes de que se ejecute do_something_that_throws() , por lo que el error que se produce dentro de la devolución de llamada nunca se detecta.

Por lo tanto, intentar / capturar es básicamente inadecuado en muchos casos, y no siempre es obvio si algo ejecuta el código de forma asíncrona o no. Afortunadamente, javascript con su peculiar lenguaje de devolución de llamada asíncrono de un solo hilo y su soporte para cierres reales ofrece una alternativa elegante: manejo de errores de estilo de paso de continuación. Simplemente pase la respuesta adecuada a cualquier error como función, por ejemplo:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);
    
respondido por el tdammers 13.04.2012 - 23:44
20

Muchas de estas respuestas son un poco antiguas y no tienen en cuenta las nuevas características de ES7 async y await .

Con async / await ahora puede obtener un flujo de control asíncrono como desee:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: '[email protected]', subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

Obtenga más información sobre async / await aquí . Puedes usar async / await ahora usando babel .

    
respondido por el Dana Woodman 16.11.2015 - 00:13
15

try-catch en javascript es tan válido y útil como en cualquier otro idioma que los implemente. Hay una razón importante por la que no se usa tanto en javascript como en otros idiomas. Es la misma razón por la que se considera a javascript como un lenguaje de guiones feo, es la misma razón por la que la gente piensa que los programadores de javascript no son programadores reales:

  • Javascript es un lenguaje increíblemente accesible y generalizado

El mero hecho de que tantas personas estén expuestas a javascript (en virtud del único lenguaje compatible con los navegadores) significa que tiene muchos códigos no profesionales por ahí. Por supuesto, también hay muchas razones menores:

  • algunas cosas en javascript son asíncronas y por lo tanto no son catch capaces (cosas asíncronas)
  • se ha hablado mucho sobre cómo try-catch tiene un gran impacto en el rendimiento. Tiene un poco de éxito en el rendimiento , pero para la mayoría de los códigos, vale la pena .
  • javascript se implementó (desafortunadamente) de una manera que a menudo ignora los errores (por ejemplo, cambiando automáticamente las cadenas a números)

Independientemente, debe usarse try-catch , pero por supuesto debería aprenda cómo usarlos correctamente - como todo lo demás en programación.

    
respondido por el user250878 24.05.2014 - 21:11
6

Creo que gran parte de la razón por la que try..catch es poco frecuente en JavaScript es porque el lenguaje tiene una tolerancia al error bastante alta. La gran mayoría de las situaciones se pueden manejar mediante el uso de verificaciones de código, buenos valores predeterminados y eventos asíncronos. En algunos casos, simplemente usar un patrón evitará problemas:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

Algunos de los problemas principales en otros idiomas que hacen que se produzcan excepciones simplemente no existen en JS. Tipo casting no es necesario la gran mayoría de las veces. En su lugar, el método preferido suele ser la verificación de características (hacer cumplir una interfaz particular):

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

Con la adición de async / await al idioma, try..catch es cada vez más frecuente. Como las promesas son la forma asíncrona de try..catch , tiene sentido que uno deba esperar:

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

para ser escrito como:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}
    
respondido por el zzzzBov 13.04.2012 - 19:27
3

Posiblemente otra razón por la que no se usa tanto try / catch en Javascript es que el constructo no estaba disponible en las primeras versiones de Javascript ... se agregó más tarde.

Como resultado, algunos navegadores antiguos no lo admiten. (De hecho, puede causar un error de analizador / sintaxis en algunos navegadores más antiguos, algo que es más difícil de "programar de forma defensiva" en comparación con la mayoría de los otros tipos de errores).

Más importante aún, ya que inicialmente no estaba disponible, las funciones incorporadas de Javascript que se lanzaron inicialmente (lo que se denominaría funciones de "biblioteca" en muchos idiomas) no lo utilizan. (No funciona muy bien "detectar" un error de someobject.somefunction () si no "lanza", sino que simplemente devuelve "nulo" cuando encuentra un problema.)

Otra posible razón es que el mecanismo try / catch no parecía ser necesario inicialmente (y todavía no parece tan útil). Realmente es necesario solo cuando las llamadas se anidan rutinariamente a varios niveles de profundidad; simplemente devolver algún tipo de ERRNO funcionaría bien para las llamadas directas (aunque para que sea realmente útil cuando esté disponible, la mejor práctica en la mayoría de los idiomas es usarlo en todas partes en lugar de solo en llamadas profundamente anidadas). Como originalmente se esperaba que la lógica de Javascript fuera pequeña y simple (después de todo, es solo un complemento de una página web :-), no se esperaba que las llamadas a funciones estuvieran profundamente anidadas, por lo que no parecía necesario un mecanismo de prueba / captura.

    
respondido por el Chuck Kollars 22.05.2013 - 05:12

Lea otras preguntas en las etiquetas