最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to watch a promise in angularJS? - Stack Overflow

programmeradmin1浏览0评论

Goal: $scope.finalArray = $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);

First approach

 $scope.arrayFromPromise1 = [];
 $scope.arrayFromPromise2 = [];

 someService.query1()
   .then(function(success){
      $scope.arrayFromPromise1 = success.data;
      return someService.query2();
   })
   .then(function(success){
      $scope.arrayFromPromise2 = success.data;
      $scope.finalArray =  $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);
   });

Second approach

$scope.arrayFromPromise1 = [];
$scope.arrayFromPromise2 = [];

function getData1(){
  someService.query1().then(function(success){
    $scope.arrayFromPromise1 = success.data
  });
}

function getData2(){
  someService.query2().then(function(success){
   $scope.arrayFromPromise2 = success.data;

   $scope.finalArray =  $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);
  });
}

getData1();
getData2();

The Second approach will throw an error depending on the time of the first promise from getData1 is finished. Can use $scope.$watch inside getData2 so I can watch the changes from $scope.arrayFromPromise1 ? Any hints that is different from chaining promises ?

Goal: $scope.finalArray = $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);

First approach

 $scope.arrayFromPromise1 = [];
 $scope.arrayFromPromise2 = [];

 someService.query1()
   .then(function(success){
      $scope.arrayFromPromise1 = success.data;
      return someService.query2();
   })
   .then(function(success){
      $scope.arrayFromPromise2 = success.data;
      $scope.finalArray =  $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);
   });

Second approach

$scope.arrayFromPromise1 = [];
$scope.arrayFromPromise2 = [];

function getData1(){
  someService.query1().then(function(success){
    $scope.arrayFromPromise1 = success.data
  });
}

function getData2(){
  someService.query2().then(function(success){
   $scope.arrayFromPromise2 = success.data;

   $scope.finalArray =  $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);
  });
}

getData1();
getData2();

The Second approach will throw an error depending on the time of the first promise from getData1 is finished. Can use $scope.$watch inside getData2 so I can watch the changes from $scope.arrayFromPromise1 ? Any hints that is different from chaining promises ?

Share Improve this question asked Jun 29, 2016 at 8:13 que1326que1326 2,3454 gold badges43 silver badges59 bronze badges 5
  • Did you try/consider including a callback to the then? Actually, the second getData should be invoked AFTER the promise from the second is pleted. – FDavidov Commented Jun 29, 2016 at 8:16
  • Not sure what you suggest, example ? – que1326 Commented Jun 29, 2016 at 8:18
  • Very simple. Invoke the first getData (getData1()) with a promise and a callback which could be getdata2. getData2 should also include a callback that would be invoked upon pletion. In this second callback you can implement the concat. What I mean, you should not trigger in parallel two asynchronous processes that need to converge at some point in time, unless you have a mechanism that would synchronize them upon pletion (like rendezvous in the old Ada language). – FDavidov Commented Jun 29, 2016 at 8:24
  • The solution posted by @fdomig is doing what I suggested (serializing the two invocations). I must ment though that I prefer a clearer way of coding. – FDavidov Commented Jun 29, 2016 at 8:26
  • The question title is confusing, doesn't reflect the post. Please consider changing it. – Jeroen Commented Jun 29, 2016 at 8:29
Add a ment  | 

5 Answers 5

Reset to default 4

Waiting for a bunch of promises to be done and then acting on the info is a simple task using the $q.all method.

//We are returned a promise with a .then block to extract the data
//this is making a certain assumption that we are using the $http service
//where as using another such as $resource or restangular will "unwrap"
//the data for us...

var query1Promise = someService.query1().then(function(res) { return res.data; });
var query2Promise = someService.query2().then(function(res) { return res.data; });

$q.all([query1Promise, query2Promise])
    .then(function(promises) {
         $scope.finalArray = promises[0].concat(promises[1]);
    });

This (dirty) solution would work:

someService.query1().then(function (success1) {
    someService.query2().then(function (success2) {
        $scope.finalArray = success1.data.concat(success2.data);
    });
});

Second solution with $watch

Still dirty, but works:

$scope.array1 = [];
$scope.array2 = [];
$scope.finalArray = [];

someService.query1().then(function (success1) {
    $scope.array1 = success.data;
});

$scope.$watchCollection('array1', function (newData, oldData) {
    someService.query2().then(function (success) {
        $scope.finalArray = newData.concat(success.data);
    });
});

Cleaner solution

Use $q.all() to wait for multiple promises to get resolved and use the data then to do something:

$q.all([someService.query1(), someService.query2()]).then(function (results) {
    $scope.finalArray = results[0].data.concat(results[1].data);
});

How about this:

$scope.finalArray = [];

someService.query1()
   .then(function(response){
      $scope.finalArray = $scope.finalArray.concat(response.data);
   });

someService.query2()
   .then(function(response){
      $scope.finalArray = response.data.concat($scope.finalArray);
   });

Both calls will be done asynchronously, in parallel. Whenever one's ready it'll change the finalArray on the scope. To ensure the result of query1 is placed before query2 you can play around with what to pass- and call to concat.

The advantage is that results from one query can trickle in and cause UI updates before the other one is down. If that's actually a downside for your business, then I remend using the approach from another answer that utilizes the all function.

You can use $q.all() to wait for both promises, and then concat your results:

$q.all([someService.query1(), someService.query2()])
.then(function(dataSet) {
  $scope.finalArray = dataSet[0].data.concat(dataSet[1].data);
});

You can use this for as many promises as you need.

How about trying Promise.all:

var promise = Promise.all([someService.query1(), someService.query2()]);

promise.then(function(result){
   $scope.arrayFromPromise1 = result[0];
   $scope.arrayFromPromise2 = result[1];
  
   $scope.finalArray = $scope.arrayFromPromise2.concat($scope.arrayFromPromise1);
});

发布评论

评论列表(0)

  1. 暂无评论