【问题标题】:Return function value AFTER for-loop endsfor循环结束后返回函数值
【发布时间】:2015-08-08 11:39:55
【问题描述】:

我有以下功能,我按顺序进入控制台false 然后truetruefalse 之后 1-2 秒出现。仅当没有上传文件时,我才需要该函数返回 false。

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

【问题讨论】:

  • 那是以AJAX为例,我的代码怎么做?
  • 在你的例子中,我假设 bucket.upload 是一个 AJAX 调用
  • 我假设是,它是 Amazon S3。不过,在 AJAX 调用运行之前,函数不会返回 uploaded 吗?

标签: javascript function for-loop asynchronous return


【解决方案1】:

我最终使用了另一种更适合我的方法。

我也在使用.ajaxStop()https://api.jquery.com/ajaxStop/。这基本上可以让我知道所有文件何时上传(如果有)。

【讨论】:

    【解决方案2】:

    这里有一个异步问题:

    当您执行循环时,您会为每次迭代调用带有回调的函数bucket.upload(当操作完成时将调用它)。但是当最后一次调用 yo bucket.upload 完成时,您的循环结束,但不是在所有回调完成时。

    所以你的返回线在所有回调之前被调用。

    如果您能理解这一点,您也可以理解异步函数永远不会返回某些内容(因为函数必须在结束之前等待某些内容),而是在所有完成后调用回调函数。 (在本例中为回调参数)

    要正常工作,您必须使用像 async (Doc here) 这样的库

    这样使用它:

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

    【讨论】:

    • 指出某人使用异步库作为解决他的问题的要求既令人困惑又不必要。只需要介绍回调是如何工作的。
    • 如果你理解了回调的概念,你就可以理解这样一个事实,即你在调用最终回调之前先列出一个要等待的回调列表。要等待回调列表,您必须使用 async 或 step 之类的库。
    【解决方案3】:

    嗯,处理异步代码总是有点复杂。

    你应该改变你的方法并在你的方法签名中传递一个回调函数:

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

    【讨论】:

    • 在您的代码中,上传的返回将在 bicket.upload 回调之前执行。
    • 并且在这段代码中,当第一个文件完成时调用最终回调(uploadFeaturedImg 参数)。它不等待所有其他人
    • 你们说得对,其实我只是想指出回调函数的使用。我的错! (刚刚加入社区)