简体   繁体   中英

Execute ajax call only after javascript loop has finished

Below is the code I am using which basically passes multiple files to be uploaded. In the loop each file is resized client side and then uploaded.

I want to execute an ajax call after the loop is finished uploading the photos. The ajax call basically reloads a specific div and refreshes the photos.

How do I prevent the ajax call from executing until the loop has finished.

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

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

(just the top part 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();
        }
    }
} 

You can use any promise library to do this. Here is example of 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/

One or more of the methods in your resizeAndUpload() function must be happening asynchronously. Which means they'll do their thing in the background while the rest of your javascript is run and they should fire an event when they are complete. You will want to call the ajax method once the last one of these methods has complete and event fired. For example, the fileReader methods are asychronous. Which means you will 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 you have uploaded 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM