Estaba escribiendo código que hace algo parecido a esto:
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 " antipatrón diferido " o " Promise
antipatrón de constructor " respectivamente, ¿qué tiene de malo este código y por qué se llama antipatrón ?
javascript
promise
q
bluebird
es6-promise
Benjamin Gruenbaum
fuente
fuente
getStuffDone
contenedor de funciones y simplemente usar el literal Promise?catch
bloque en elgetStuffDone
envoltorio el antipatrón?Promise
ejemplo nativo , también tiene envoltorios de funciones innecesarios para los manejadores.then
y.catch
(es decir, podría ser simplemente.then(resolve).catch(reject)
). Una tormenta perfecta de antipatrones.Respuestas:
El antipatrón diferido (ahora antipatrón de construcción explícita) acuñado por Esailija es un antipatrón común que son nuevos en las promesas, lo hice yo mismo cuando lo usé por primera vez. El problema con el código anterior es que no puede utilizar el hecho de que promete la cadena.
Las promesas pueden encadenarse
.then
y usted puede devolverlas directamente. Su códigogetStuffDone
puede reescribirse como:Las promesas tienen que ver con hacer que el código asincrónico sea más legible y comportarse como un código sincrónico sin ocultar ese hecho. Las promesas representan una abstracción sobre un valor de operación de una sola vez, resumen la noción de una declaración o expresión en un lenguaje de programación.
Solo debe usar objetos diferidos cuando convierte una API a promesas y no puede hacerlo automáticamente, o cuando escribe funciones de agregación que se expresan más fácilmente de esta manera.
Citando a Esailija:
fuente
.defer()
API en el constructor de promesas más nuevo (y seguro), no desaprobó (de ninguna manera) la noción de construir promesas :)¿Qué tiene de malo?
Eres afortunado. Desafortunadamente, probablemente no, ya que es probable que hayas olvidado algunos casos extremos. En más de la mitad de los casos que he visto, el autor se ha olvidado de encargarse del controlador de errores:
Si se rechaza la otra promesa, esto pasará desapercibido en lugar de propagarse a la nueva promesa (donde se manejaría), y la nueva promesa permanece pendiente para siempre, lo que puede provocar fugas.
Lo mismo sucede en el caso de que su código de devolución de llamada provoque un error, por ejemplo, cuando
result
no tiene unproperty
y se produce una excepción. Eso no se manejaría y dejaría la nueva promesa sin resolver.Por el contrario, el uso se
.then()
ocupa automáticamente de estos dos escenarios y rechaza la nueva promesa cuando ocurre un error:El antipatrón diferido no solo es engorroso, sino también propenso a errores . Usar
.then()
para encadenar es mucho más seguro.De Verdad? Bueno. Sin embargo, esto será bastante detallado y abundante, especialmente si utiliza una biblioteca prometedora que admita otras funciones como la cancelación o el envío de mensajes. ¿O tal vez lo hará en el futuro, o desea cambiar su biblioteca por una mejor? No querrás volver a escribir tu código para eso.
Los métodos de las bibliotecas (
then
) no solo admiten de forma nativa todas las características, sino que también pueden tener ciertas optimizaciones. Su uso probablemente acelerará su código, o al menos permitirá que se optimice en futuras revisiones de la biblioteca.¿Cómo lo evito?
Por lo tanto, cada vez que se encuentre creando manualmente una
Promise
o unaDeferred
promesa existente, consulte primero la API de la biblioteca . El antipatrón diferido a menudo es aplicado por personas que ven las promesas [solo] como un patrón de observación, pero las promesas son más que devoluciones de llamada : se supone que son componibles. Cada biblioteca decente tiene muchas funciones fáciles de usar para la composición de promesas de todas las maneras imaginables, cuidando todas las cosas de bajo nivel con las que no desea lidiar.Si ha encontrado la necesidad de componer algunas promesas de una nueva manera que no sea compatible con una función auxiliar existente, escribir su propia función con aplazamientos inevitables debería ser su última opción. Considere cambiar a una biblioteca más funcional y / o presente un error en su biblioteca actual. Su responsable de mantenimiento debería poder derivar la composición de las funciones existentes, implementar una nueva función auxiliar para usted y / o ayudar a identificar los casos límite que deben manejarse.
fuente
setTimeout
, donde el constructor podría usarse pero no considerarse "Promite constructor anitpattern"?setTimeout
", sino " la función ensetTimeout
sí misma ".setTimeout
", sino" la funciónsetTimeout
misma "" ¿Puede describir, vincular a las diferencias, entre los dos?setTimeout
es claramente diferente de la función ensetTimeout
sí , ¿no?