为什么来自 Promise `.then` 方法的回调是一种反模式

Why are Callbacks from Promise `.then` Methods an Anti-Pattern

我在 Whosebug 上看到了人们建议为 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 服务 returns 承诺并让 .then 方法执行回调函数感觉像是一种不健康的控制反转。

如何重构这样的代码以及如何解释为什么原来的方法不是一个好主意?

你应该把它改成

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

然后在其他模块中使用

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

至于为什么它是反模式,我想说的是,首先,它不允许您进一步链接 success/fail 处理程序方法。其次,它控制处理从调用者模块到被调用模块的响应(这在这里可能不是非常重要,但它仍然强加相同的控制反转)。最后,你在你的代码库中添加了 promises 的概念,这对于一些队友来说可能不是那么容易理解,但是然后使用 promises 作为回调,所以这真的没有意义。

代码可以重构如下:

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

通过承诺服务 return 并使用承诺的 .then 方法,可以实现相同的功能并获得以下好处:

  • promise 可以保存并用于链接

  • 承诺可以保存并用于避免重复相同的 $http 调用。

  • 错误信息被保留,可以用.catch方法检索。

  • 承诺可以转发给其他客户端