异步 Angular Promise 和变量初始化

Asynchronous Angular Promise and Variable Initialization

我有一个看起来像这样的工厂:

app.factory('thingFactory', function($http) {

    var factory = {};   
    var things = [];

    factory.refreshThings = function() {
        return $http.post('/GetThings');
    }

    factory.initializeThings = factory.refreshThings()
        .then(function(response) {
            things = response.data;
        }, function(response){
            // some error handling code here...
        });

    factory.getThings = function() {
        return things;
    }

    return factory;
}

和控制器

app.controller('myController', function($scope, thingFactory) {
    $scope.things = thingFactory.getThings();
}

由于 promises 的异步性质,以及正在初始化的其他集合(除了 things),我是否应该关心 getThings() 返回一个空数组,从而在$http.post()呼叫已解决?

这是更好的选择吗?

app.controller('myController', function($scope, thingFactory) {
    $scope.things = []

    thingFactory.initializeThings
        .then(function(response) {
            $scope.things = response.data;
        }, function (response) {
            // some error handling code here...
        });
}

有没有安全的替代方案,我可以让控制器不考虑承诺,而只是安全地从工厂获取集合?

你的代码肯定有问题。工厂在被控制器使用之前不会被实例化,因此 things 在被控制器调用之前不会被初始化,此时 initializeThings 将在您调用 [=14 之前被调用=],这很可能 return 一个空数组。此外,遵循 "let's hope it's there" 方法绝不是一个好主意。

我看到您可以采用两种方法:getThings 接受回调作为参数或者它 return 是一个承诺,它可能看起来像这样:

  1. 回调 - 我更喜欢回调而不是承诺,但这是个人的事情。此外,我使用受 NodeJS 启发的语法:

    var things; // no need to initialize array
    
    // callback -> function (error, things) {}
    factory.getThings = function (callback) {
      if (things) {
        return callback(null, things);
      }
    
      factory.refreshThings()
        .then( function (response) {
            things = response.data;
            return callback(null, things);
        }, function (reason) {
            return callback(reason);
        });
    }
    
  2. Promises - 不是最好的语法,但你明白了

    factory.getThings = function () {
      var d = $q.defer();
      // I'm sure there's a better way to do this, but setting
      // this in a timeout will allow the promise to return so that
      // you can try to return it.
      $timeout( function () {
        if (things) {
           return d.resolve(things);
        }
    
        factory.refreshThings()
          .then( function (response) {
            things = response.data;
            return d.resolve(things);
          }, function (reason) {
            return d.reject(reason);
          });
      });
    
      return d.promise;
    }
    

附带说明一下,如果您使用的是 RESTful API,则应使用 GET 获取信息而不是 POST。