Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular promise in async loop function

Tags:

angularjs

I have an upload function which loops through the selected files and adds them on the servers file system.

Upload factory

app.factory('uploadFactory', function ($upload, $q) {

    var uploadFactory = {};

    var image = {
        Models: [],
        Images: [],
        uploadImages: function () {
            var defer = $q.defer();
            for (var i = 0; i < this.Models.length; i++) {
                var $file = this.Models[i].file;
                (function (index) {
                    $upload
                        .upload({
                            url: "/api/upload/",
                            method: "POST",
                            file: $file
                        })
                        .success(function (data, result) {
                            // Add returned file data to model
                            var imageObject = {
                                Path: data.Path,
                                Description: image.Models[index].Description,
                                Photographer: image.Models[index].Photographer
                            };
                            image.Images.push(imageObject);

                            defer.resolve(result);
                        });
                })(i);
            }
            return defer.promise;
        }
    };

    uploadFactory.image = function () {
        return image;
    };

    return uploadFactory;
});

In my controller

$scope.imageUpload = new uploadFactory.image;
$scope.create = function () {
    var uploadImages = $scope.imageUpload.uploadImages();
    uploadImages.then(function () 
        $scope.ship.Images = $scope.imageUpload.Images;
        shipFactory.create($scope.ship).success(successPostCallback).error(errorCallback);
    });
};

My problem is that the promise only holds the promise for the first upload through the looping. I have read something about $q.all() but I'm not sure how to implement it to work.

How can I make it to hold through the whole loop? Thanks!

Solution

var image = {
    Models: [],
    Images: [],
    uploadImages: function () {
        for (var i = 0; i < this.Models.length; i++) {
            var $file = this.Models[i].file;
            var defer = $q.defer();

            (function (index) {
                var promise = $upload
                    .upload({
                        url: "/api/upload/",
                        method: "POST",
                        file: $file
                    })
                    .success(function (data, result) {
                        // Add returned file data to model
                        var imageObject = {
                            Path: data.Path,
                            Description: image.Models[index].Description,
                            Photographer: image.Models[index].Photographer
                        };
                        image.Images.push(imageObject);

                        defer.resolve(result);
                    });
                promises.push(promise);
            })(i);
        }
        return $q.all(promises);
    }
};
like image 257
Lars Avatar asked Oct 02 '22 13:10

Lars


1 Answers

You're right $q.all() is the way to go here (totally untested -- but i think this is at least the right direction..):

app.factory('uploadFactory', function ($upload, $q) {

    var uploadFactory = {};

    var image = {
        Models: [],
        Images: [],
        uploadImages: function () {

            var promises = [];

            for (var i = 0; i < this.Models.length; i++) {

                var $file = this.Models[i].file;
                var response = $upload
                    .upload({
                        url: "/api/upload/",
                        method: "POST",
                        file: $file
                    })
                    .success(function (data, result) {
                        // Add returned file data to model
                        var imageObject = {
                            Path: data.Path,
                            Description: $file.Description,
                            Photographer: $file.Photographer
                        };
                        image.Images.push(imageObject);
                    });

                promises.push(response);
            }
            return $q.all(promises);
        }
    };

    uploadFactory.image = function () {
        return image;
    };

    return uploadFactory;
});
like image 51
jlb Avatar answered Oct 05 '22 12:10

jlb