5

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

1 Answer 1

4

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

7 Comments

This makes all the images to be uploaded, but look at my controller code above. The uploadImages function is executed, but the code inside the .then(function () { is not, it just stops there. Does the uploadImages return correctly?
is it possible that some of the uploads are failing? Maybe add a .error callback to the $upload.upload promise and see..
No, I already have an error callback, I've just not added it with the code in this question for easier reading. All my uploads are valid and successful
Can you put a breakpoint in the success handler and make sure the defer.resolve(result) line is executed? Unfortunately I can't really see what could be wrong here.
Great. Just an FYI, instead of making new promises via $q.deferred() you can append the return value of $upload.upload(..) to the array that gets passed into $q.all().
|

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.