¿Por qué las devoluciones de llamada de los métodos Promise `.then` son un antipatrón?
He visto respuestas en StackOverflow donde la gente sugiere proporcionar una función de devolución de llamada a un servicio AngularJS.
app.controller('tokenCtrl', function($scope, tokenService) {
tokenService.getTokens(function callbackFn(tokens) {
$scope.tokens = tokens;
});
});
app.factory('tokenService', function($http) {
var getTokens = function(callbackFn) {
$http.get('/api/tokens').then (function onFulfilled(response) {
callbackFn(response.data);
});
};
return {
getTokens: getTokens
};
});
Esto me parece un antipatrón. El $http
servicio devuelve promesas y que .then
los métodos ejecuten funciones de devolución de llamada se siente como una inversión de control poco saludable.
¿Cómo se refactoriza un código como este y cómo se explica por qué la forma original no era una buena idea?
Deberías cambiarlo a
var getTokens = function() {
return $http.get('/api/tokens');
};
Y luego, en otro módulo, use
yourModule.getTokens()
.then(function(response) {
// handle it
});
En cuanto a por qué es un antipatrón, diría que, primero, no le permite encadenar aún más sus métodos de manejo de éxito/fallo. En segundo lugar, maneja el control del procesamiento de la respuesta del módulo que llama al módulo llamado (lo que puede no ser muy importante aquí, pero aún así impone la misma inversión de control). Y finalmente, agrega el concepto de promesas a su código base, que puede no ser tan fácil de entender para algunos de los compañeros de equipo, pero luego usa promesas como devoluciones de llamada, por lo que esto realmente no tiene sentido.
El código se puede refactorizar de la siguiente manera:
app.controller('tokenCtrl', function($scope, tokenService) {
tokenService.getTokens.then ( callbackFn(tokens) {
$scope.tokens = tokens;
});
});
app.factory('tokenService', function($http) {
var getTokens = function() {
//return promise
return $http.get('/api/tokens').then (function onFulfilled(response) {
//return tokens
return response.data;
}
);
};
return {
getTokens: getTokens
};
});
Al hacer que el servicio devuelva una promesa y utilizar el .then
método de la promesa, se logra la misma funcionalidad con los siguientes beneficios:
La promesa se puede guardar y utilizar para encadenar .
La promesa se puede guardar y utilizar para evitar repetir la misma
$http
llamada.La información del error se conserva y se puede recuperar con el
.catch
método.La promesa se puede enviar a otros clientes.