¿Por qué las devoluciones de llamada de los métodos Promise `.then` son un antipatrón?

Resuelto georgeawg asked hace 8 años • 2 respuestas

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 $httpservicio devuelve promesas y que .thenlos 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?

georgeawg avatar Feb 27 '16 03:02 georgeawg
Aceptado

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.

Alex.Me avatar Feb 26 '2016 20:02 Alex.Me

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 .thenmé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 $httpllamada.

  • La información del error se conserva y se puede recuperar con el .catchmétodo.

  • La promesa se puede enviar a otros clientes.

georgeawg avatar Feb 27 '2016 07:02 georgeawg