Make ajax call only after javascript loop completes

Below is the code I am using that basically transfers multiple uploads. In the loop, each file is changed to the client side and then loaded.

I want to make an ajax call after the loop has finished loading the photos. The Ajax call basically reloads a specific div and updates the photos.

How to prevent the ajax call from executing before the loop completes.

if (window.File && window.FileReader && window.FileList && window.Blob)
    {       
        var files = document.getElementById('filesToUpload').files;    
        for(var i = 0; i < files.length; i++) 
        {
            resizeAndUpload(files[i]);


        }

        // when loop finished, execute ajax call
            $.ajax
            ({
                type: "POST",
                url: "photos.php",
                data: dataString,
                success: function(html)
                {
                    $("#photo-body").html(html);
                }       
            });
        }       
    }

function resizeAndUpload(file)
{
    var reader = new FileReader();
    reader.onloadend = function() 
    {
        var tempImg = new Image();
        tempImg.src = reader.result;
        tempImg.onload = function()
        {
            var MAX_WIDTH = 382.25;
            var MAX_HEIGHT = 258.5;
            var tempW = tempImg.width;
            var tempH = tempImg.height;

            if (tempW > tempH) 
            {
                if (tempW > MAX_WIDTH)
                {
                    tempH *= MAX_WIDTH / tempW;
                    tempW = MAX_WIDTH;
                }
            } 
            else
            {
                if (tempH > MAX_HEIGHT)
                {
                    tempW *= MAX_HEIGHT / tempH;
                    tempH = MAX_HEIGHT;
                }
            }

            var canvas = document.createElement('canvas');
            canvas.width = tempW;
            canvas.height = tempH;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(this, 0, 0, tempW, tempH);
            var dataURL = canvas.toDataURL("image/jpeg");

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(ev)
            {
                document.getElementById('filesInfo').innerHTML = 'Upload Complete';

            };
            xhr.open('POST', 'upload-resized-photos.php', true);
            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            var data = 'image=' + dataURL;
            xhr.send(data); 


        }
    }
    reader.readAsDataURL(file);
}

var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];    
function Validate(oForm)
{
    var arrInputs = oForm.getElementsByTagName("input");
    for (var i = 0; i < arrInputs.length; i++) 
    {
        var oInput = arrInputs[i];
        if (oInput.type == "file")
        {
            var sFileName = oInput.value;
            if (sFileName.length > 0)
            {
                var blnValid = false;
                for (var j = 0; j < _validFileExtensions.length; j++) 
                {
                    var sCurExtension = _validFileExtensions[j];
                    if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) 
                    {
                        blnValid = true;
                        break;
                    }
                }

                if (!blnValid) 
                {
                    alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                    return false;
                }   
            }
        }
    }
    return true;
}

      

+3


source to share


3 answers


You can wrap your $ ajax call in a function and call the function at the end of the final loop.

(just the top of your script)



if (window.File && window.FileReader && window.FileList && window.Blob) {       

    function loopFinished(){
        $.ajax
        ({
            type: "POST",
            url: "photos.php",
            data: dataString,
            success: function(html)
            {
                $("#photo-body").html(html);
            }       
        });
    }

    var files = document.getElementById('filesToUpload').files;    
    for(var i = 0; i < files.length; i++) 
    {
        resizeAndUpload(files[i]);
        if (files.length+1 == [i]){
            loopFinished();
        }
    }
} 

      

+1


source


You can use any promise library for this. Here is an example using jQuery promise

     (function ($) {
        var files = [1, 2, 3, 4],
            allPromises = [];
        for (var i = 0; i < files.length; i++) {
            var promise = resizeAndUpload(files[i]);
            allPromises.push(promise);

        }

        $.when.apply($, allPromises).done(function () {
            makeAjaxCall();
        });

        function makeAjaxCall() {
            console.log('Put Ajax call here');
        }

        function resizeAndUpload(file) {
            var defer = $.Deferred();
//Set timeout simulates your long running process of processing file
            setTimeout(function () {
                console.log('processing file ' + file);
                defer.resolve();

            }, 2000);
            return defer.promise();
        }
    })(jQuery);

      



Here is a jSFiddle http://jsfiddle.net/x6oh471f/2/

+1


source


One or more methods in your function resizeAndUpload()

must run asynchronously. This means that they will do their thing in the background while the rest of your javascript is running, and they should fire an event when they are finished. You want to call the ajax method as soon as the last of these methods is completed and the event is fired. For example, the fileReader methods are asynchronous. This means that you probably need to do something like:

FileReader.onloadend = function(){
   totalFilesLoaded = totalFilesLoaded + 1;
   if (totalFilesLoaded == files.length){
      //all files have been uploaded, run $ajax
   }
}

      

EDIT: Now that you've downloaded the rest of your code, try something like this:

window.totalFilesLoaded = 0;
var files = document.getElementById('filesToUpload').files;
window.totalFilesToLoad = files;

if (window.File && window.FileReader && window.FileList && window.Blob)
    {       

        for(var i = 0; i < files.length; i++) 
        {
            resizeAndUpload(files[i]);
        }

    }

      

Separate ajax function:

window.runAjax = function(){
           $.ajax
            ({
                type: "POST",
                url: "photos.php",
                data: dataString,
                success: function(html)
                {
                    $("#photo-body").html(html);
                }       
            });
}

      


function resizeAndUpload(file)
{
    var reader = new FileReader();
    reader.onloadend = function() 
    {

    ...

            xhr.onreadystatechange = function(ev)
            {
                document.getElementById('filesInfo').innerHTML = 'Upload Complete';


                window.totalFilesLoaded++;
                if (window.totalFilesLoaded == window.totalFilesToLoad.length){
                    window.runAjax()
                }


            };

    ...

    }
    reader.readAsDataURL(file);
}

      

0


source







All Articles