我在StackOverflow上看到了答案,有人建议为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
    };
});


在我看来,这是一种反模式。 $http服务返回promise,让.then方法执行回调函数感觉像是对控件的不健康转换。

如何重构这样的代码,以及如何解释为什么原始方法不好?理念?

评论

只是告诉人们实际使用诺言而不是忽略诺言。

我发现使用promise是一种健康的方法,因为它具有将其链接并可以控制异步调用的功能。

主要问题是then()中没有返回任何内容,因此没有地方可以捕获回调中的错误。它打破了承诺链

使用诺言会使代码也变得更短,更简单。

该服务返回一个对象没有多大意义……它需要返回一个promise,以便任何使用它的人都可以知道何时数据准备就绪。

#1 楼

您应该将其更改为

var getTokens = function() {
      return $http.get('/api/tokens');
    };


,然后在其他模块中使用

yourModule.getTokens()
  .then(function(response) {
    // handle it
  });


关于为什么一个反模式,我想说的是,首先,它不允许您进一步链接成功/失败处理程序方法。其次,它处理处理从调用者模块到被调用模块的响应的控制(这在这里可能不是很重要,但是它仍然施加相同的控制反转)。最后,您在代码库中添加了promise的概念,对于某些队友来说可能不太容易理解,但是随后将promise用作回调,因此这确实没有意义。

#2 楼

可以按以下方式重构代码:

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
    };
});


通过使服务返回promise,并使用promise的.then方法,可以实现相同的功能有以下好处:


promise可以保存并用于链接。
promise可以保存并用于避免重复相同的$http调用。
错误信息将保留并可以通过.catch方法进行检索。
承诺可以转发给其他客户端。