【问题标题】:Recursive Function to check array length [closed]检查数组长度的递归函数
【发布时间】:2021-11-20 18:05:48
【问题描述】:

我有一个名为 runningTimers 的数组,其中包含一个在后台运行但尚未完成的计时器列表。每个定时器运行 500 毫秒。如果用户按下提交按钮,我希望他们在提交表单之前等待这些计时器完成。

下面是我检查数组长度的递归函数。当数组为空时,它应该返回。

function checkTimers() {
    if (runningTimers.length < 1) {
        return true;
    } else {
        checkTimers();
    }
}

下面是提交按钮的jQuery代码。

$(document).on("click","#checkoutbtn",function(e) {
    e.preventDefault();
    var checkVariable = checkTimers();
    if (checkVariable == true) {
       $(this).html("<i class='fa fa-spinner fa-spin'></i>");
       $(this).prop('disabled',true);

       $("#cartform").submit();
    }

});

以下是 runningTimers 的设置方式

var runningTimers = [];
function updateQuantity(dataString,oid, context) {
    if (timername[oid]) {
        clearTimeout(timername[oid]);
    }
    if (runningTimers.indexOf(oid) == -1) {
        runningTimers.push(oid);
    } 
    timername[oid] = setTimeout(function() {
        const index = runningTimers.indexOf(oid);
        if (index > -1) {
            runningTimers.splice(index,1);
            console.log("removed");
        }
        //Ajax code here
        
    },500);
}

我收到以下错误:

Uncaught RangeError: Maximum call stack size exceeded
    at checkTimers (cart:692)

【问题讨论】:

  • 如果什么都不会让它不真实,那为什么还要重复呢?如果不使用返回值,那为什么还需要返回呢?
  • 这可能是回调或承诺的更好用例 - 您使用递归的方式将使其快速无限递归,并迅速达到 JS 抛出错误的最大递归深度.
  • 使用递归函数是不可能的,它会立即调用自身而不给事件循环处理异步操作的机会。
  • 您的checkTimers() 导致无限循环。 rest 的代码在做什么?听起来你想要一个 Promise 或者这里的东西。
  • 什么是设置/更改runningTimers?你可能想要new PromisePromise.all() 或类似的东西。

标签: javascript jquery recursion


【解决方案1】:

当您调用checkTimers() 时,它会一遍又一遍地调用它,并且基本上是无限循环。你永远不会给浏览器做其他事情的机会,所以它会一直运行 checkTimers() 直到它死掉。

我建议将其从 setTimeout() 重构,并改用 Promise。这使您可以在后台运行代码,并在完成后运行回调。 (或者由于您使用的是 jQuery,我们可以使用它的 Deferred 对象。)

let ajaxCalls = [];

function updateQuantity(dataString, oid, context) {
    ajaxCalls.push($.ajax(...));
}

$.ajax() 方法返回一个jqXHR 对象,我们可以将其用作Deferred

然后您可以使用$.when()“等待”所有它们完成后再运行回调。

$(document).on("click","#checkoutbtn",function(e) {
    e.preventDefault();

    $.when.apply($, ajaxCalls).then(() => {
        $(this).html("<i class='fa fa-spinner fa-spin'></i>");
        $(this).prop('disabled',true);
        $("#cartform").submit();
    });
});

【讨论】:

    猜你喜欢
    • 2017-06-06
    • 2022-01-10
    • 1970-01-01
    • 2013-01-22
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    相关资源
    最近更新 更多