w3schools then sincronas promises promesas para nodejs funciones catch javascript promise q bluebird es6-promise

javascript - then - ¿Cuál es la promesa explícita de construcción antipattern y cómo la evito?



promise typescript (2)

Estaba escribiendo código que hace algo que se parece a:

function getStuffDone(param) { | function getStuffDone(param) { var d = Q.defer(); /* or $q.defer */ | return new Promise(function(resolve, reject) { // or = new $.Deferred() etc. | // using a promise constructor myPromiseFn(param+1) | myPromiseFn(param+1) .then(function(val) { /* or .done */ | .then(function(val) { d.resolve(val); | resolve(val); }).catch(function(err) { /* .fail */ | }).catch(function(err) { d.reject(err); | reject(err); }); | }); return d.promise; /* or promise() */ | }); } | }

Alguien me dijo que esto se llama " antipatterno diferido " o " Promise constructor Promise " respectivamente, ¿qué tiene de malo este código y por qué se llama antipattern ?


¿Qué tiene de malo?

¡Pero el patrón funciona!

Eres afortunado. Desafortunadamente, probablemente no, ya que es probable que haya olvidado algún caso de ventaja. En más de la mitad de los casos que he visto, el autor ha olvidado encargarse del controlador de errores:

return new Promise(function(resolve) { getOtherPromise().then(function(result) { resolve(result.property.example); }); })

Si se rechaza la otra promesa, esto pasará inadvertido en lugar de propagarse a la nueva promesa (donde se manejará), y la nueva promesa quedará pendiente para siempre, lo que puede provocar fugas.

Lo mismo sucede en el caso de que su código de devolución de llamada cause un error, por ejemplo, cuando el result no tiene una property y se lanza una excepción. Eso no se manejaría y dejaría sin resolver la nueva promesa.

Por el contrario, el uso de .then() se encarga automáticamente de estos dos escenarios y rechaza la nueva promesa cuando ocurre un error:

return getOtherPromise().then(function(result) { return result.property.example; })

El antipattern aplazado no solo es engorroso, sino también propenso a errores . Usar .then() para el encadenamiento es mucho más seguro.

¡Pero lo he manejado todo!

De Verdad? Bueno. Sin embargo, esto será bastante detallado y abundante, especialmente si utiliza una biblioteca de promesa que admita otras funciones como la cancelación o el paso de mensajes. ¿O tal vez lo hará en el futuro, o desea cambiar su biblioteca por una mejor? No querrás reescribir tu código para eso.

Los métodos de las bibliotecas ( then ) no solo soportan de forma nativa todas las características, también pueden tener ciertas optimizaciones en su lugar. Es probable que su uso haga que su código sea más rápido, o al menos permita que lo optimicen las futuras revisiones de la biblioteca.

¿Cómo lo evito?

Por lo tanto, cuando se encuentre creando manualmente una Promise o Deferred y haya promesas ya existentes, verifique primero la API de la biblioteca . El antipatterno diferido se aplica a menudo por personas que ven las promesas [solo] como un patrón de observador, pero las promesas son más que devoluciones de llamada : se supone que son compilables. Cada biblioteca decente tiene muchas funciones fáciles de usar para la composición de promesas en todas las formas posibles, cuidando todas las cosas de bajo nivel con las que no quiere lidiar.

Si ha encontrado la necesidad de redactar algunas promesas de una manera nueva que no sea compatible con una función auxiliar existente, escribir su propia función con los diferidos inevitables debe ser su última opción. Considere cambiar a una biblioteca con más funciones y / o presentar un error en su biblioteca actual. Su mantenedor debe poder derivar la composición de las funciones existentes, implementar una nueva función auxiliar para usted y / o ayudar a identificar los casos de borde que deben manejarse.


El antipatterno diferido (ahora antipatrón de construcción explícita) acuñado por Esailija es un antipatrón común que es nuevo en las promesas, lo hice yo mismo cuando lo utilicé por primera vez. El problema con el código anterior es que no se puede utilizar el hecho de que promete la cadena.

Las promesas se pueden encadenar con .then y se pueden devolver las promesas directamente. Su código en getStuffDone puede ser reescrito como:

function getStuffDone(param){ return myPromiseFn(param+1); // much nicer, right? }

Las promesas consisten en hacer que el código asíncrono sea más legible y se comporten como código síncrono sin ocultar ese hecho. Las promesas representan una abstracción sobre un valor de una operación de tiempo, abstraen la noción de una declaración o expresión en un lenguaje de programación.

Solo debe usar objetos diferidos cuando está convirtiendo una API en promesas y no puede hacerlo automáticamente, o cuando está escribiendo funciones de agregación que se expresan más fácilmente de esta manera.

Citando a Esailija:

Este es el anti-patrón más común. Es fácil caer en esto cuando realmente no entiendes las promesas y piensas que son emisores de eventos glorificados o utilidad de devolución de llamada. Recapitulemos: las promesas consisten en hacer que el código asíncrono retenga la mayoría de las propiedades perdidas del código síncrono, como la sangría plana y un canal de excepción.