AngularJS:在循环中调用工厂方法

时间:2015-08-05 11:48:45

标签: javascript angularjs promise factory

我有一个工厂方法,如下所示:

angular.module('GridSamplesApp')
.factory('registerPostFactory', function($resource, $q, WebRequest) {
    var getMessage = function(Upddata, token, dataurl)
    {
            var deferred = $q.defer();
             var settings = {
                data: Upddata,
                headers: {
                  'Content-Type': 'application/JSON',
                  'x-csrf-token' : token
                },
                method: 'POST',
                url: dataurl,
                withCredentials: true
            };
            WebRequest.requestRaw(settings).then(
    function(response) {
      // data from app sec

      var msg = response;

     deferred.resolve(msg);
    },
    function(error) {
      console.log('Error retrieving message', error);
      deferred.reject('Error retrieving message', error);
    });

  return deferred.promise;
    };


  return {
   getMessage: getMessage
  };
   });

我有一个看起来像

的控制器
$scope.getLogs = function()
{

  $.each($scope.modifiedSN, function(i, e) {
      if ($.inArray(e, result) == -1) result.push(e);
  });

  $scope.inputs.push({SN:'', Key:'', status:'', log:''});
  for(var i=0; i<result.length; i++)
  {
    var j = result[i];
    if ($scope.data[j].SerialNumber !== "")
    {


  var Upddata = {};
  Upddata['IConvRuleFlg'] = '';
  Upddata['SrNum'] = $scope.data[j].SerialNumber;
  Upddata['LvEmailId'] = 'abc@xyz.com';
  Upddata['WKey'] = $scope.data[j].WtyKey;

            registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
                function(response) {
                  $scope.msg = response.headers["custommessage"];
                  $scope.data[j].AutolinkErrorlog = $scope.msg;
                  $scope.inputs.push({SN: $scope.data[j].SerialNumber, Key: $scope.data[j].WtyKey, status: response.headers["msgtype"], log: $scope.msg});
                },
                function(error) {
                    console.log('Error reading msg: ', error);
                  }
                  );
          }
  }

};

这个问题是它只接受数组中的最后一个元素,因为它是一个异步调用而循环不会等待响应,我尝试使用$q.all()但是无法弄清楚如何实现这个,有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

根据我的理解,你的工厂工作正常,就像@RaviMone所说,在for循环中使用异步回调代码,你会惊讶于初学者经常陷入陷阱。此外,我看到$scope.msg,不知道它来自何处以及它是如何工作的,但由于您的呼叫的异步和并行特性,它可能会显示各种呼叫的错误值,如果它每次呼叫更改,您应该考虑序列化你的电话。

编写$scope.getLogs的更简洁方法可能是(我减少了jQuery的使用,使用了ES5的东西,如果你必须支持遗留系统,你可以使用this):

$scope.getLogs = function(){
  var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
  $scope.modifiedSN.forEach(function(value) {
      if (result.indexOf(value) < 0) result.push(e);
  });
  $scope.inputs.push({SN:'', Key:'', status:'', log:''});

  var promises = result.map(function(val){
    return $scope.data[val];
  }).filter(function(val){
    return val && val.SerialNumber !== "";  // first check if $scope.data[j] exists
  }).map(function(val){
    return registerPostFactory.getMessage({
        IConvRuleFlg: '',
        LvEmailId: '',
        WKey: val.WtyKey,
        SrNum: val.SerialNumber
    }).then(function(response){
        $scope.msg = response.headers["custommessage"];
        val.AutolinkErrorlog = $scope.msg;
        $scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
    }).catch(function(e){
        console.log('Error reading msg: ', e);
    });
  });

  $q.all(promises)
    .then(function(resArray){
        console.log('get all logs...');
    }).catch(function(e){
        console.log('some error: ', e);
    });
};

修改

如果你想按顺序完成它们:

$scope.getLogs = function(){
  var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
    , serialPromise = $q.when(1);   // just initializing a promise.
  $scope.modifiedSN.forEach(function(value) {
      if (result.indexOf(value) < 0) result.push(e);
  });
  $scope.inputs.push({SN:'', Key:'', status:'', log:''});

  result.map(function(val){
    return $scope.data[val];
  }).filter(function(val){
    return val && val.SerialNumber !== "";  // first check if $scope.data[j] exists
  }).forEach(function(val){
    var datum = {
            IConvRuleFlg: '',
            LvEmailId: '',
            WKey: val.WtyKey,
            SrNum: val.SerialNumber
    };
    serialPromise = serialPromise.then(function(){  // adding a new promise to the chain.
        return registerPostFactory.getMessage(datum);
    }).then(function(response){
        $scope.msg = response.headers["custommessage"];
        val.AutolinkErrorlog = $scope.msg;
        $scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
    }).catch(function(e){
        console.log('Error reading msg: ', e);
    });
  });

  serialPromise.then(function(){
        console.log('got all logs...');
    }).catch(function(e){
        console.log('some error: ', e);
    });
};

答案 1 :(得分:0)

这里你必须使用闭包,我修改了你的代码,

(function(data) {
    //console.log(data) //You can notice here, you are getting all individual loop objects
    var Upddata = {};
    Upddata['IConvRuleFlg'] = '';
    Upddata['SrNum'] = data.SerialNumber;
    Upddata['LvEmailId'] = 'abc@xyz.com';
    Upddata['WKey'] = data.WtyKey;

    registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
        function(response) {
            $scope.msg = response.headers["custommessage"];
            $scope.data[j].AutolinkErrorlog = $scope.msg;
            $scope.inputs.push({
                SN: data.SerialNumber,
                Key: data.WtyKey,
                status: response.headers["msgtype"],
                log: $scope.msg
            });
        },
        function(error) {
            console.log('Error reading msg: ', error);
        }
    );
})($scope.data[j]);