angularjs - promises - ¿Es este un "antipatrón diferido"?
promise angular 6 (3)
Me resulta difícil entender el "antipatrón diferido". Creo que lo entiendo en principio, pero no he visto un ejemplo súper simple de lo que es un servicio, con una promesa diferente y una con antipatrón, así que pensé que trataría de hacer la mía, pero viendo que no súper al respecto, primero obtendría algunas aclaraciones.
Tengo lo siguiente en una fábrica (SomeFactory):
//url = ''data.json'';
return {
getData: function(){
var deferred = $q.defer();
$http.get(destinationFactory.url)
.then(function (response) {
if (typeof response.data === ''object'') {
deferred.resolve(response.data);
} else {
return deferred.reject(response.data);
}
})
.catch(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
La razón por la que estoy comprobando que es un objeto es solo para agregar una capa simple de validación en
$http.get()
Y a continuación, en mi directiva:
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
})
.catch(function(response) {
//Do error handling here
});
Ahora, para mi comprensión, este es un antipatrón. Porque la promesa diferida original capta el error y simplemente se lo traga. No devuelve el error, así que cuando se llama a este método "getData", tengo que hacer otra captura para obtener el error.
Si esto NO es un antipatrón, ¿alguien puede explicar por qué ambos requieren una especie de "devolución de llamada"?
Cuando comencé a escribir esta fábrica / directiva, anticipé tener que hacer una promesa diferida en alguna parte, pero no
.catch()
tener que
.catch()
en ambos lados (también estaba pensando que podría hacer que la fábrica devolviera la respuesta o el error si hice un
SomeFactory.getData()
¿Es este un "antipatrón diferido"?
Sí lo es.
El ''antipatrón diferido'' ocurre cuando se crea un nuevo objeto diferido redundante para ser resuelto desde dentro de una cadena de promesa
.
En su caso, está utilizando $ q para devolver una promesa para algo que implícitamente devuelve una promesa.
Ya tiene un objeto Promesa (el
$http service
sí mismo devuelve una
promise
), ¡así que solo necesita devolverlo!
Aquí está el ejemplo súper simple de lo que es un servicio, con una promesa diferida y una con aspecto antipatrón,
Esto es antipatrón
app.factory("SomeFactory",[''$http'',''$q'']){ return { getData: function(){ var deferred = $q.defer(); $http.get(destinationFactory.url) .then(function (response) { deferred.resolve(response.data); }) .catch(function (error) { deferred.reject(error); }); return deferred.promise; } } }])
Esto es lo que debes hacer
app.factory("SomeFactory",[''$http'']){
return {
getData: function(){
//$http itself returns a promise
return $http.get(destinationFactory.url);
}
}
mientras que ambos se consumen de la misma manera.
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
},function(response) {
//Do error handling here
});
No hay nada malo con ninguno de los ejemplos (al menos sintácticamente) ... pero el primero es redundante ... ¡y no es necesario!
Espero eso ayude :)
Usar el constructor $ q es un antipatrón diferido
ANTI-PATRÓN
vm.download = function() { var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"; return $q(function(resolve, reject) { var req = { method: ''POST'', url: url, responseType: ''arraybuffer'' }; $http(req).then(function(response) { resolve(response.data); }, function(error) { reject(error); }); }); }
CORRECTO
vm.download = function() {
var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
var req = {
method: ''POST'',
url: url,
responseType: ''arraybuffer''
};
return $http(req).then(function(response) {
return response.data;
});
}
El servicio $ http ya devuelve una promesa. Usar el constructor $ q es innecesario y propenso a errores.
Diría que es el anti-patrón diferido clásico porque está creando objetos diferidos innecesarios. Sin embargo, está agregando algo de valor a la cadena (con su validación). Por lo general, en mi opinión, el antipatrón es particularmente malo cuando se crean objetos diferidos por muy poco o ningún beneficio.
Entonces, el código podría ser mucho más simple.
$q
promesas
$q
tienen una pequeña característica documentada de envolver automáticamente cualquier cosa devuelta dentro de una promesa en una promesa (usando
$q.when
).
En la mayoría de los casos, esto significa que no debería tener que crear manualmente un diferido:
var deferred = $q.defer();
Sin embargo, así es como la documentación demuestra cómo usar las promesas con
$q
.
Entonces, puede cambiar su código a esto:
return {
getData: function(){
return $http.get(destinationFactory.url)
.then(function (response) {
if (typeof response.data === ''object'') {
return response.data;
} else {
throw new Error(''Error message here'');
}
});
// no need to catch and just re-throw
});
}