1

I have a factory method which looks like below:

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
  };
   });

I have a controller which looks like

$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'] = '[email protected]';
  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);
                  }
                  );
          }
  }

};

The issue with this is that it only takes the last element in the array since it is an asynchronous call and the loop will not wait for the response, I tried using $q.all() but could not figure out how to implement this, can anyone please help?

2

2 Answers 2

1

From what I understand, your factory works ok, and like @RaviMone said, it is with the usage of async callback code within for loop, you ll be surprised how often beginners fall into that trap. Also, I see a $scope.msg, not sure where it comes from and how it works, but due to async and parallel nature of your calls, it might be display wrong values for various calls, if it changes per call, you should think about serializing your call.

A cleaner way to write $scope.getLogs might be( I have reduced the usage of jQuery, used ES5 stuff, if you have to support legacy systems, you can use 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);
    });
};

Edit:

if you want them done in sequence:

$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);
    });
};
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, the resArray i get is undefined, I am not sure how to correct this. Can you please help?
resArray is undefined, in all the promises, the then block returns nothing.
0

Here you have to use closure, I have modified your code,

(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'] = '[email protected]';
    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]);

1 Comment

Hi, this still considers only the last record in the loop.It does not wait for the response to come back, i want to put the next loop on hold until i get the response for the previous item.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.