0

I have the following loop that checks through each row in a grid and then saves the rows that have been changed:

for (var i = 0, len = $scope.grid.data.length; i < len; i++) {
    if (!angular.equals($scope.grid.data[i], $scope.grid.backup[i])) {

        var rowData = $scope.grid.data[i]
        var idColumn = $scope.entityType.toLowerCase() + 'Id';
        var entityId = rowData[idColumn];
        var entityResource = $resource('/api/:et/:id', { et: $scope.entityType }, { update: { method: 'PUT' } });
        $scope.grid.showMessage = true;
        $scope.grid.message = 'Saving Id: ' + entityId + ' ...';
        entityResource.update({ id: entityId }, $scope.grid.data[i],
            function (result) {
                angular.copy(result, $scope.grid.data[i]);
                angular.copy(result, $scope.grid.backup[i]);
                $timeout(function () {
                    $scope.grid.showMessage = false;
                    $scope.$broadcast('gridSetPristine');
                }, 1000);
            }, function (result) {
                var msg = result.data.exceptionMessage;
                $scope.grid.message = "Error saving grid data";
                $timeout(function () {
                    $scope.grid.showMessage = false;
                }, 5000);
            })
    }
}

This works good if all the rows save okay. However I would like to change it so it stops if one of the saves fails.

The problem I have is that the update functions do not return until later. How can I make it do the update, wait for the result and then either continue or break out of the for loop if there is an error? Note that I am using 1.2 RC3 version of Angular. Also I do not mind that this may be slow as usually there will be only less than three rows that have been updated in my grid each time the save button is pressed which then calls the code in the for loop.

4

2 回答 2

1

We have promises and array methods to make your solution easier! Yay :-)

Here's what we'll do:

  1. We'll filter out from our grid-data all the objects that haven't been updated.
  2. We'll map our array of grid data to an array of requests to update the server data, then represent those by promises. It looks like $http would be simpler than $resource here, so we'll use that.
  3. We'll use $q.all to see when all those requests have fulfilled ... or if one gets rejected, we'll catch that.

Sample code:

var entityIdColumn = $scope.entityType.toLowerCase() + 'Id';
var requests = $scope.grid.data
  .filter(function(rowData, i) {
    return !angular.equals(rowData, $scope.grid.backup[i]);
  })
  .map(function(rowData, i) {
    var entityId = rowData[entityIdColumn];
    return $http.post('/api/' + $scope.entityType + '/' + entityId, rowData);
  });
$q.all(requests).then(function(allResponses) {
  //if all the requests succeeded, this will be called, and $q.all will get an
  //array of all their responses.
  console.log(allResponses[0].data);
}, function(error) {
  //This will be called if $q.all finds any of the requests erroring.
});

Here is an explanation of promises if you don't understand them: http://sebastianfastner.de/javascript-promises-explained.html

于 2013-11-12T13:32:16.293 回答
0

You should execute the code for updating the resource in a function to be called each time the success calback is invoked, you can follow this scheme:

$scope.saveNextRow = function(i) {
    ...
    entityResource.update(..,
        function (result) {
            ...
            if (++i < $scope.grid.data.length) {
                $scope.saveNextRow(i);
            }
        },
        function (result) {
            ...
        });
};

i = 0;
$scope.saveNextRow(i);
于 2013-11-12T13:44:52.110 回答