简体   繁体   中英

Return function value AFTER for-loop ends

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

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).

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

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

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