Angular方式等待另一个异步资源?

时间:2014-09-15 15:14:17

标签: javascript angularjs asynchronous

让我们在Angular应用程序中说,我有一个输出数据列表的控制器,根据配置的规则进行格式化。两个数据都应异步获取:

  • list config(例如,要显示的属性)
  • 数据

好的,因为使用$ http / ngResource / Restangular从后端检索数据(配置和数据),代码可能如下所示:

angular.module('myApp').controller('ListCtrl', function (Backend) {
  var config,
      data;

  var draw = function() {
    Backend.getData(function(retrievedData) {
      // data retrieved asynchronously, store them:
      data = retrievedData;

      // to generate the list, we need both config and data:

      if (!config) {
        // <---- How can I wait until config has been loaded?
      }

      $scope.list = generateList(config, data);
  }

  // let's say, Backend.getConfig would make an asynch call and fetch the config data
  Backend.getConfig(function(retrievedConfig) {
    // config data retrieved asynchronously, store them:
    config= retrievedConfig;
  });
}

我希望你明白这一点:要生成列表并将其分配给范围,需要两个输入数据。但由于配置在短期内没有变化,我不想使用$ q.all()等待两者。因此,配置数据应仅在第一次获取,然后保存在控制器中(由变量&#34; config&#34;引用)。这是在上面的代码中实现的,但如果有人触发了'draw()&#39;功能和配置仍在加载,我如何制作代码&#34;等待&#34;直到获取必要的配置数据?

我想起了$ emit / $ broadcast,但我不喜欢这个想法,因为这对于这个目标来说感觉就像是错误的武器。

还有其他可能吗?

1 个答案:

答案 0 :(得分:0)

我会用另一个只在需要时执行调用的服务包装Backend.getConfig()调用并返回一个promise。其他时候,它返回一个使用缓存值解析的promise。 E.g:

.service("getCachedConfig", function(Backend, $q) {
    var cachedConfig;

    return function getCachedConfig(cb) {
        var deferred = $q.defer();
        deferred.promise.then(cb); // install the callback, to adhere to your API; I would consider using promises all the way...
        if( cachedConfig != null ) {
            deferred.resolve(cachedConfig);
        }
        else {
            Backend.getConfig(function(retrievedConfig) {
                cachedConfig = retrievedConfig;
                deferred.resolve(cachedConfig);
            });
        }
        return deferred.promise;
    };
})

现在你可以做$q.all(Backend.getPromiseForData(...), getCachedConfig())(假设方法Backend.getPromiseForData返回一个保证)。配置只会被提取一次。您可以轻松地增强此功能以添加缓存过期。