AngularJS:使用$ q同步触发ajax调用

时间:2014-01-20 16:31:28

标签: ajax angularjs

是否可以使用$ q在AngularJS中同步触发ajax请求?

我有一长串vehicles,每个vehicle都有events与他们相关联,我需要检索每个eventdetails的{​​{1}}用户扩展了列表。

现在,如果用户扩展了列表,我会异步拨打15个调用,这似乎导致了我正在消耗的API问题,所以我想看看如果我等待,性能是否会提高每个请求在解雇下一个请求之前完成。

我正在尝试实施event以延迟下一个请求,直到上一个请求完成,但是我似乎无法使用该服务,这就是我目前所拥有的:

$q

这仍然是异步发射,我在哪里错了?

我理解同步触发请求并不是最好的主意,目前我只想知道API的性能是否有所改善。

3 个答案:

答案 0 :(得分:9)

  1. 您不需要$q来实施承诺,因为$http会返回承诺。

  2. _.each在没有特别等待承诺的情况下触发所有回调。

  3. 只要您的承诺得到解决,您所做的只是致电retrieveData所有事件,并且由于您没有先拨打电话,它甚至不能正常工作

  4. 你可以这样做一些递归调用:

    var retrieveEventDetails = function(events) {
        var evt = events.shift();
        $http({
            url: '/api/eventdetails',
            method: 'POST',
            data: {
                event_number: evt.number
            },
            isArray: true
        }).then(function(response){
            console.log(response.data);
            retrieveEventDetails(events);
        });
    }
    

答案 1 :(得分:3)

我确实认为您应该使用$q ,因为您的应用程序的其他部分可能需要获得承诺。

一个很好的例子是 $routeProvider解析选项

我做了一点demo in plunker

解决方案:

  • retrieveData function应返回一个函数(返回一个promise)而不是一个promise。
  • 这样我们就可以创建一个承诺链: promise.then(fn).then(fn).then(fn).then(null,errorFn)
  • 我们必须解决第一个带来链条的承诺。
var retrieveEventDetails = function(events) {
    // events is array

    var deferred = $q.defer();
    var promise = deferred.promise;

    var retrieveData = function(data) {
        return function(){      
            return $http({
                url: '/api/eventdetails',
                method: 'POST',
                data: {
                    event_number: data.number
                },
                isArray: true
            })
        }
    }

    deferred.resolve();

    return events.reduce(function(promise, single_event){
        return promise.then(retrieveData(single_event));
    }, promise);
}

答案 2 :(得分:1)

我不确定你在这里需要$q。在这个例子中,每一条数据一旦从呼叫中返回就会在控制器中注册。

<强> Live demo (click).

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, myService) {
  $scope.datas = myService.get();
});

app.factory('myService', function($http) {
  var myService = {
    get: function() {
      var datas = {};

      var i=0;
      var length = 4;
      makeCall(i, length, datas);

      return datas;
    }
  }

  function makeCall(i, length, datas) {
    if (i < length) {
      $http.get('test.text').then(function(resp) {
        datas[i] = resp.data+i;
        ++i;
        makeCall(i, length, datas);
      }); 
    }
  }

  return myService;
});

以下是使用$q.all()的方法,您可以在将所有数据传递给控制器​​之前等待所有数据: Live demo (click).

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, myService) {
  myService.get().then(function(datas) {
    $scope.datas = datas;
  })
});

app.factory('myService', function($q, $http) {
  var myService = {
    get: function() {
      var deferred = $q.defer();

      var defs = [];
      var promises = [];

      var i=0;
      var length = 4;

      for(var j=0; j<length; ++j) {
        defs[j] = $q.defer();
        promises[j] = defs[j].promise;
      }

      makeCall(i, length, defs);

      $q.all(promises).then(function(datas) {
        deferred.resolve(datas);
      });

      return deferred.promise;
    }
  }

  function makeCall(i, length, defs) {
    if (i < length) {
      $http.get('test.text').then(function(resp) {
        defs[i].resolve(resp.data+i);
        ++i;
        makeCall(i, length, defs);
      })
    }
  } 

  return myService;
});