0

I have the following function and I'm getting in the console false then true in that order. The true comes like 1-2 seconds after the false. I need the function to return false ONLY if no files were uploaded.

function uploadFeaturedImg()
{
    var uploaded = false,
        files = featuredImg.files;

    if (files.length > 0)
    {
        for (var i = 0, len = files.length; i < len; i++)
        {
            var params = {
                Key: 'tournament/image/'+files[i].name,
                ContentType: files[i].type,
                Body: files[i]
            };

            bucket.upload(params, function(err, data)
            {
                if (!err)
                {
                    if (!uploaded) uploaded = true;
                    console.log(uploaded);
                }
                else
                {
                    fileAlert(files[i].name);
                }
            });
        }
    }

    console.log(uploaded);
    return uploaded;
};
jstudios
  • 856
  • 1
  • 9
  • 26
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – tcigrand May 26 '15 at 17:02
  • That is using AJAX as an example, how can I do it with my code? – jstudios May 26 '15 at 17:14
  • In your example, I'm assuming bucket.upload is an AJAX call – tcigrand May 26 '15 at 17:17
  • I'm assuming so, it's Amazon S3. Still, won't the function return `uploaded` before the AJAX call runs? – jstudios May 26 '15 at 17:34

3 Answers3

0

I ended up using another approach that worked for me better.

I'm also using .ajaxStop(): https://api.jquery.com/ajaxStop/. This basically lets me know when all files have been uploaded (if any).

jstudios
  • 856
  • 1
  • 9
  • 26
-1

There is an asynchrone problem here:

When you do your loop, you call for each iteration the function bucket.upload with a callback (it will be call when the action is finished). But your loop is ended when the last call yo bucket.upload is done, but NOT when all the callback are done.

So you return line is called BEFORE all the callback.

If you can understand that, you can also understand an asyncron function never return something (cause the function have to wait for something before end) but call a callback function when all it's done. (in this case the callback param)

To work fine you have to use a lib like async (Doc here)

Use it like that :

if (files.length > 0) {
  async.each(
    files, 
    function(file, cb) {
      // This function will be called for each iteration
      // ... 

      // Call your funciton here
      bucket.upload(params, function(err, data) {
         // When the callback is done, call the end for the iteration
         cb();
      }
    }, 
    function(err) {
      // This function is called only when ALL callback are done. 
      callback(true);  // All upload are done correctly
    });
  );
} 
else { 
  // No files to upload 
  callback(false);  
}
Arthur
  • 4,870
  • 3
  • 32
  • 57
  • pointing someone to use an async library as a requirement to solve his problem is both confusing, and unnessary. Just need to cover how callbacks work. – Cooper Buckingham May 26 '15 at 17:24
  • If you understand the concept of callback, you can understand the fact you avec a list of callback to wait before call the final callback. And to wait a list of callback you have to use a lib like async, or step. – Arthur May 26 '15 at 17:27
-2

Well, it is always a bit complicated to deal with asynchronous code.

You should change your approach and pass a callback function in the signature of your method:

function uploadFeaturedImg(callback)
{
    var uploaded = false,
    files = featuredImg.files;

    if (files.length > 0)
    {
        for (var i = 0, len = files.length; i < len; i++)
        {
            var params = {
                Key: 'tournament/image/'+files[i].name,
                ContentType: files[i].type,
                Body: files[i]
            };

            bucket.upload(params, function(err, data)
            {
                if (!err)
                {
                    if (!uploaded) uploaded = true;
                    if(callback) callback();          //Do what you were supposed to do with the result of your function in this callback function
                }
                else
                {
                    fileAlert(files[i].name);
                }
            });
        }
     }

    return uploaded;
};
Lyncee
  • 112
  • 3
  • In your code, the return uploaded will be executed BEFORE callback on bicket.upload. – Arthur May 26 '15 at 17:08
  • And on this code, the final callback (uploadFeaturedImg param) is called when the first file is done. It not waiting for all others – Arthur May 26 '15 at 17:19
  • You are right guys, in fact I just wanted to point the use of a callback function. My bad! (just joined the community here) – Lyncee May 27 '15 at 08:12