通过递归循环同步ajax请求



我正试图通过向发送邮件的脚本发出ajax请求来向许多接收者发送时事通讯邮件。为了确保上一个请求完成(这样就不会达到浏览器并发请求的最大数量),我使用了递归循环函数。

这个问题已经在不同的变体中被问过几次了,但我找不到任何有助于我的答案。

我尝试过的:

var receiverarray = <?php echo json_encode($receiverarray); ?>; // All data is correctly received from PHP
var nrofreceivers = '<?php echo count($receiverarray); ?>';
nrofreceivers = parseInt(nrofreceivers);
function sendmailreceivers(receiverarray, callback) {
    try  {
        var a = 0;
        recur_loop(a);
        function recur_loop(i) {
            var num = i;
            if (num < nrofreceivers) {
                var count = num + 1;
                var percentage = (count / receiverarray.length) * 100;
                percentage = Math.round(percentage);
                var loadingtext = String(count) + " van " + String(nrofreceivers) + " (" + String(percentage) + "%)";
                $('#loadingtext').html(loadingtext);
                var thisreceiverarray = receiverarray[num];
                $.ajax({
                    type: "POST",
                    url: "https://www.domain.com/scripts/sendmail.php", // Script works fine
                    data: {
                        'from_mail': '<?php echo $webmastermailaddress; ?>',
                        'from_name': 'Webmaster name',
                        'to_mail': thisreceiverarray.email,
                        'to_name': thisreceiverarray.name,
                        'reply_name': 'Business name',
                        'reply_mail': 'Business mail address',
                        'diff_mailer': '',
                        'mail_content': '<HTML>The html mail content</HTML>',
                        'mail_subject': '<?php echo $subject; ?>'
                    },
                    success: function(){
                        recur_loop(count);
                    },
                    error: function() {
                        throw "Error!";
                    }
                });
            }
        };
        callback();
    }
    catch(err) {
        throw "Error!";
    }
}

这适用于前3个邮件地址。然后,由于未知的原因,函数完成,回调确保执行下一个函数(我将用户重定向到感谢页面)。

因此,看起来每封邮件都已发送,因为该功能完成时没有出错,但实际上只发送了3封邮件。

我已经花了很多天的时间寻找答案并试图解决它,但没有运气。控制台中没有错误?

为什么函数过早结束?

我试着稍微改进一下你的代码,但它仍然不完美:

var receiverarray = <?php echo json_encode($receiverarray); ?>;
function sendmailreceivers(callback) {
    try {
        recur_loop(0);
        function recur_loop(i) {
            if (i === receiverarray.length) {
              return callback();
            }
            var percentage = Math.round((i / receiverarray.length) * 100);
            var loadingtext = i + " van " + receiverarray.length + " (" + percentage + "%)";
            $('#loadingtext').text(loadingtext);
            var thisreceiverarray = receiverarray[i];
            $.ajax({
                type: "POST",
                url: "https://www.domain.com/scripts/sendmail.php", // Script works fine
                data: {
                    'from_mail': '<?php echo $webmastermailaddress; ?>',
                    'from_name': 'Webmaster name',
                    'to_mail': thisreceiverarray.email,
                    'to_name': thisreceiverarray.name,
                    'reply_name': 'Business name',
                    'reply_mail': 'Business mail address',
                    'diff_mailer': '',
                    'mail_content': '<HTML>The html mail content</HTML>',
                    'mail_subject': '<?php echo $subject; ?>'
                },
                success: function(){
                    recur_loop(i + 1);
                },
                error: function(err) {
                    callback(err);
                }
            });
        }
    } catch(err) {
        callback(err);
    }
}
sendmailreceivers(function(err) {
    if (err) {
        console.error(err.stack);
        alert('Error!');
    } else {
        alert('Done');
    }
});

几句话:

  • 您在第一个请求完成之前已呼叫callback
  • try { ... } catch(err) { throw "Error"; }将吞下一条有意义的错误消息,并将其替换为"错误"——这不是很有用
  • 如果str包含文本而非html代码,则最好使用.text(str)而不是.html
  • 添加err作为回调函数的第一个参数以返回可能的错误通常是个好主意
  • String(val)parseInt(val, 10)仅用于转换值的类型
  • 除了在旧的PHP版本中,您不需要在使用变量之前将所有内容都存储在变量中。例如,将函数的返回值作为参数传递是完全可以的

最新更新