¿Cuándo se considera .then(éxito, fracaso) un antipatrón para las promesas?

Resuelto user2127480 asked hace 10 años • 0 respuestas

Eché un vistazo a las preguntas frecuentes sobre la promesa de bluebird , en las que se menciona que .then(success, fail)es un antipatrón . No entiendo bien su explicación en cuanto a tryy catch. ¿Qué hay de malo en lo siguiente?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

Parece que el ejemplo sugiere que la siguiente es la forma correcta.

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

¿Cual es la diferencia?

user2127480 avatar Jul 10 '14 02:07 user2127480
Aceptado

¿Cual es la diferencia?

La .then()llamada devolverá una promesa que será rechazada en caso de que la devolución de llamada arroje un error. Esto significa que, cuando su éxito loggerfalla, el error se pasará a la siguiente .catch()devolución de llamada, pero no a la faildevolución de llamada que va al lado success.

Aquí hay un diagrama de flujo de control :

diagrama de flujo de control de entonces con dos argumentos diagrama de flujo de control de la cadena de captura

Para expresarlo en código síncrono:

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

El segundo log(que es como el primer argumento de .then()) solo se ejecutará en el caso de que no haya ocurrido ninguna excepción. El bloque etiquetado y la breakdeclaración se sienten un poco extraños, esto es en realidad para lo que sirve Pythontry-except-else (¡lectura recomendada!).

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

El catchregistrador también manejará excepciones de la llamada exitosa del registrador.

Hasta aquí la diferencia.

No entiendo muy bien su explicación en cuanto al intento de captura.

El argumento es que, por lo general, desea detectar errores en cada paso del procesamiento y que no debe usarlo en cadenas. La expectativa es que solo tenga un controlador final que maneje todos los errores, mientras que, cuando usa el "antipatrón", los errores en algunas de las devoluciones de llamada no se manejan.

Sin embargo, este patrón es realmente muy útil: cuando desea manejar errores que ocurrieron exactamente en este paso y desea hacer algo completamente diferente cuando no ocurrió ningún error, es decir, cuando el error es irrecuperable. Tenga en cuenta que esto está ramificando su flujo de control. Por supuesto, esto a veces es deseable.


¿Qué hay de malo en lo siguiente?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

Que tuviste que repetir tu devolución de llamada. prefieres querer

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

También podrías considerar usarlo .finally()para esto.

Bergi avatar Jul 09 '2014 20:07 Bergi

Los dos no son del todo idénticos. La diferencia es que el primer ejemplo no detectará una excepción lanzada en su successcontrolador. Entonces, si su método solo debe devolver promesas resueltas, como suele ser el caso, necesita un catchcontrolador final (u otro thencon un successparámetro vacío). Claro, puede ser que su thencontrolador no haga nada que pueda fallar, en cuyo caso usar un parámetro de 2 thenpodría estar bien.

Pero creo que el punto del texto al que vinculaste es que thenes más útil que las devoluciones de llamada en su capacidad de encadenar un montón de pasos asincrónicos, y cuando realmente haces esto, la forma de 2 parámetros de thensutilmente no se comporta como se esperaba. , por el motivo anterior. Es particularmente contradictorio cuando se usa en la mitad de la cadena.

Como alguien que ha hecho muchas cosas asincrónicas complejas y se ha topado con rincones como este más de lo que me gustaría admitir, realmente recomiendo evitar este antipatrón y optar por el enfoque de controlador separado.

acjay avatar Jul 09 '2014 20:07 acjay