将在JavaScript中递归调用Web服务导致StackOverflow

时间:2016-06-13 18:46:56

标签: javascript ajax web-services recursion asp.net-web-api

我有一个迁移过程可能需要2到3天才能完成。我担心以下实现可能会因为它的递归方面而引发StackOverFlow异常。 JavaScript是否实际构建了一个巨大的堆栈才能执行此代码?如果是这样,那么什么是更好的实施?我可能会将此服务称为大约1000万次。

function mainFunc() {
        var url = getMyUrl();
        $.ajax({
            url: url,
            type: "POST",
            contentType: "application/json;charset=utf-8",
            dataType: "json",
            success: function (remaining) {
                if(remaining > 0) {
                   mainFunc();
                }
                else {
                    alert('done');
                }
            },
            error: function (x, e) {
                alert('error!');
            }
        });
    }

3 个答案:

答案 0 :(得分:1)

因为$.ajax是异步的,所以在远程服务器响应之前,它不会调用success函数。换句话说,在每次迭代之后,JS引擎将基本上“睡眠”直到它得到响应,然后使用success函数继续。所以这在技术上不是递归的例子。堆栈应该保持相当小,无论它需要多少迭代(假设没有其他因素你没有在这里显示有助于堆栈)。

答案 1 :(得分:1)

首先,这听起来不像是应该从浏览器中完成的事情,而是处理服务器端。

话虽如此,你的递归是异步发生的,所以堆栈溢出肯定不会发生 根据您的确切代码(更具体地说,哪些值确切地包含在闭包中),这可能会开始堆积内存。您还将使用额外的内存,因为每次调用mainFunc时都会重新创建成功和错误函数。

通过在mainFunc之外声明这些函数,然后在mainFunc函数内传递对它们的引用,可以相当容易地解决此函数内存分配问题。

这样做不会让你完全免于阻止内存异常。这实际上取决于实际代码以及每次迭代时保留的引用。

为了确定您的代码是否在这个漫长的过程中依赖于资源,您将必须阅读代码并找出代码“泄漏”的位置,或者深入了解内存分析选项:

https://developer.chrome.com/devtools/docs/javascript-memory-profiling

分解闭包的示例:

function mainFuncSuccess(remaining) {
    if(remaining > 0) {
       mainFunc();
    }
    else {
        alert('done');
    }
}


function mainFuncError() {
    alert('error!');
}

function mainFunc() {
        var url = getMyUrl();
        $.ajax({
            url: url,
            type: "POST",
            contentType: "application/json;charset=utf-8",
            dataType: "json",
            success: mainFuncSuccess,
            error: mainFuncError
        });
    }

答案 2 :(得分:1)

不,因为您没有在mainFunc中存储需要稍后使用的任何内容。没有任何对象需要存储在函数的范围内。

在chrome中,您可以使用window.performance.memory

检查内存