离子角度服务仅在控制器调用后返回数据

时间:2017-01-22 02:28:02

标签: angularjs asynchronous ionic-framework

我有一个服务,它会执行两个$ http.get来从两个源获取数据并将concat转换为数组并将其返回给控制器。

angular.module('starter.controllers').factory('GetDataList', function ($http) {
var arrDataList = [];
var postData1 = {
    "param": "1"
};

var postData2 = {
    "param": "2"
};

$http({
    method: 'GET',
    url: 'https://localhost/search',
    data: postData1
})
.then(function (items) {
    debugger
    arrDataList = arrDataList.concat(items.data.list);
});

$http({
    method: 'GET',
    url: 'https://localhost/locate',
    data: postData2
})
   .then(function (items) {
   debugger
   arrDataList = arrDataList.concat(items.data.list);
   });

return {
    getAPIData: function () {
        debugger
        return arrDataList;
    }
};
});

在我的控制器中,我称之为:

$scope.GetList = function () {
   debugger
   $scope.item = GetDataList.getAPIData();

   $scope.$broadcast('scroll.infiniteScrollComplete');
}

当我在控制台中使用调试器时,我注意到

1)首先调用getAPIData(),但其中包含数据

2)控制器触发了下一个调试器GetDataList.getAPIData();没有返回$scope.Item的任何数据

3)最后一个调试器到达$ http调用,这正如我在控制台中观察到的那样正确地返回数据。但它之后从未到达控制器端,因此移动应用程序中没有显示数据

我读到了角度异步调用的自然行为,所以这似乎是正常的。但就我而言,我该怎么做才能确保数据能够到达控制器?

非常感谢

2 个答案:

答案 0 :(得分:0)

您应该按照以下

进行同步
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope,serviceDemo) {
  $scope.name = 'World';

});
app.factory('serviceDemo', function ($http) {
    var arrDataList = [];
    var postData1 = []; var postData2 =[]

    var firstMethod=function(){ 
                $http({ 
                    method: 'GET',
                    url: 'a.json'
                }) 
                .then(function (response) {
                  console.log(response);
                    postData1=response.data;
                    arrDataList.push(postData1);
            //      console.log(postData1);
                secondMethod();     //put the second method call here
                });
    }
    var secondMethod=function(){
                $http({
                    method: 'GET',
                  url: 'b.json' 
                })
                   .then(function (response) {
                   postData2=response.data;
                arrDataList.push(postData2);
                   console.log(arrDataList);
                   });
     }
     var getAPIData= function () {
                firstMethod();

                return arrDataList;
     }

    return {
            getAPIData: getAPIData
    };
    });

修改:

您需要在第一个方法的成功块中调用第二个方法。通过这种方式,您的第一个方法被执行,当获取结果时,您的第二个方法被执行,然后只有控制将来自第一个方法块。

<强> LIVE DEMO

答案 1 :(得分:0)

要在不失去性能的情况下实现这一目标,您应该使用$ q.all(),这样它会使您的请求保持异步,并且一旦所有承诺都得到解决,它将返回数据。不要尝试同步方法,因为这会降低您的表现。 您可以像这样使用它:

您的工厂:

app.factory('GetDataList', function($q, $http) {
  var promises = [];
  var arrDataList = [];
  var requests = [{
    url: 'https://localhost/search',
    postData: {
      "param": "1"
    }
  }, {
    url: 'https://localhost/locate',
    postData: {
      "param": "2"
    }
  }];

  angular.forEach(requests, function(req) {
    executeRequest(req);
  })

  function resolveData(data) {
    debugger
    if (arrDataList.length === 0) {
      arrDataList = data.data;
    } else {
      arrDataList = arrDataList.concat(data.data);
    }
  }

  function executeRequest(req) {
    var promise = $http({
        url: req.url,
        method: 'GET',
        data: req.postData
      })
      .then(resolveData);

    promises.push(promise)
  }

  return {
    getAPIData: function() {
      debugger
      return $q.all(promises).then(function() {
        return arrDataList
      });
    }
  }

});

你的控制器:

  $scope.GetList = function() {
    debugger
    GetDataList.getAPIData().then(function(item) {
      $scope.item = item
    });

    $scope.$broadcast('scroll.infiniteScrollComplete');
  }

我们在这里做的是异步执行requests数组中的每个请求(使用其urlpostData)并保存数组中的promise。当调用getApiData时,它返回一个将在$q.all(promises)之后调用的函数,这意味着它将在所有这些promise完成后返回数据(promises会询问arrDataList是否为空如果不是,则汇总新数据。

这样你就可以保持异步调用!在控制器内部,您会收到承诺而不是数据本身。