AngularJS Array of Promises

10,441

You must push a promise, not a deferred, to the promises array:

promises.push(deferred.promise);

It helps if you think about it like this:

  • the promise is a read-only object you want to return to the consumers
  • deferred is the modifier of that read-only promise and you want to keep it for yourself
Share:
10,441
Daniel Bonnell
Author by

Daniel Bonnell

Senior fullstack software engineer with executive management experience seeking a challenging but rewarding opportunity with a forward thinking team on an innovative product.

Updated on August 16, 2022

Comments

  • Daniel Bonnell
    Daniel Bonnell almost 2 years

    Can anyone help me with some Angular promises? I have the following functions that should take in an array of file objects, iterate over them, and upload each one. During each iteration, a promise object is pushed to an array of promises. Within my upload function I have a cycle function with a .then() attached, which should not be called until all the promise objects have resolved. I think my code looks correct, but it's not working right. The images upload, but cycle(files).then() is being called immediately, rather than once the promises array resolves.

    function upload(files) {
        var uploadCount = files.length;
        function cycle(files) {
            var promises = [];
            for (var i = 0; i < files.length; i++) {
                var deferred = $q.defer();
                promises.push(deferred);
                var file = files[i];
                Upload.upload({
                    url: '/photos.json',
                    file: file
                }).success(function(){
                    $scope.progressCurrentCount += 1;
                    deferred.resolve();
                });
            };
            return $q.all(promises);
        };
    
        cycle(files).then(function(result) {
            if(uploadCount > 1) {
                $scope.lastAction = 'uploaded ' + uploadCount + ' photos';
            } else {
                $scope.lastAction = 'uploaded ' + uploadCount + ' photo';
            }
            $scope.showSuccessModal = true;
            $scope.uploading = false;
            $scope.failedUploads = [];
            $scope.newPhotos = {
                token: $scope.token,
                files: undefined
            };
            photoUploadBtn.removeClass('disabled');
        })
    };
    

    Final working code*

    Rather than setting var deferred = $q.defer(); pushing deferred.promise into the promises array, and then resolving deferred in my .success() callback, which wasn't working, I just push my Upload.upload() function without the .success() callback into promises, and then pass that to $q.all(), which does all the lifting.

    function upload(files) {
        var uploadCount = files.length;
        function cycle(files) {
            var promises = [];
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
                var promise = Upload.upload({
                    url: '/photos.json',
                    file: file
                });
                promises.push(promise);
            };
            return $q.all(promises);
        };
    
        cycle(files).then(function(result) {
            if(uploadCount > 1) {
                $scope.lastAction = 'uploaded ' + uploadCount + ' photos';
            } else {
                $scope.lastAction = 'uploaded ' + uploadCount + ' photo';
            };
            $scope.showSuccessModal = true;
            $scope.uploading = false;
            $scope.failedUploads = [];
            $scope.newPhotos = {
                token: $scope.token,
                files: undefined
            };
            photoUploadBtn.removeClass('disabled');
            getPhotos(q);
        })
    };
    
  • Daniel Bonnell
    Daniel Bonnell almost 9 years
    Thanks, that was most of the solution I needed! I also came upon this article, which made me realize that I should approach things slightly differently. I'll put my final code in my post above.