如何在异步计算

时间:2016-12-06 21:37:58

标签: angularjs background promise pouchdb

我正在使用Angular 1 / Ionic 1 / PouchDB开发单页应用程序。

在主页上,我想显示一些合成信息,这些信息来自对大量数据的计算,并且可能需要几秒钟(我需要通过查询承诺查询PouchDB数据库,然后执行一些操作)计算)。

因此,我不想阻止主页显示,并立即显示,没有这种合成。然后,一旦后台工作完成,我想填充主页的相应<div>

我的问题是如何做到这一点......

我尝试了各种方法:

  • UI-Router中的resolve无效,因为它会阻止主页在计算所有内容之前显示,这正是我想要避免的内容

  • 在表单中显示$scope.syntheticData变量(开头为空),并在计算完成后将此变量设置为计算值。但主页未更新。即使使用$scope.$apply()

  • 在计算完成时使用$rootScope.$broadcast触发事件。我使用$scope.$on从主页控制器收听此事件。我收到了该事件,然后将$scope.syntheticData设置为收到的值,但它仍然不起作用。即使使用$scope.$apply

我觉得这是非常基本的东西,但我找不到解决方法。非常感谢你的帮助!

回答Harshil Shah的评论,这里是控制器中我的代码的一个版本来更新范围:

  // ctrl function
  $scope.syntheticData = {};

  $scope.$on('updateSynthetic', function() {
    $scope.syntheticData = {}; // trial to make sure Angular sees a change on next line...
    $scope.syntheticData.info1 = synthesis.data.info1;
    $scope.$apply();
  }); 

synthesis是一个服务,通过PouchDB查询检索数据库数据,承诺进行计算then(),并将结果存储到synthesis.data.info1(以及info2, info3,...)

如果我在$ on事件回调中放入一个console.log,它会出现,所以当从服务中触发事件时会调用它。

1 个答案:

答案 0 :(得分:0)

让函数最初返回一个空对象,然后在异步操作完成时填充该对象:

function expensiveData(params) {
    var emptyObject = {};
    emptyObject.$resolved = false;
    var derivedPromise = asynchronousAPI(params).then(function(data) {
        //Do computation here
        //..
        //Populatate emptyObject
        angular.copy(data, emptyObject);
        emptyObject.$resolved = true;

        //return data for chaining
        return data;
    });

    emptyObject.$promise = $q.when(derivedPromise);

    return emptyObject;
});

如果派生的promise来自AngularJS框架之外,$q.when将确保执行AngularJS摘要周期。如果没有,没有伤害。

然后在客户端代码中:

$scope.syntheticData = expensiveData(params);

syntheticData.$promise.then(function(data) {
    //DO more stuff here
});

HTML

<div>{{syntheticData}}</div>

在每个AngularJS摘要周期中,插值{{ }}创建的观察者将检查syntheticData的值,并在DOM可用时将其放在DOM上。