【问题标题】:Can calling setTimeout in a closure cause a memory leak?在闭包中调用 setTimeout 会导致内存泄漏吗?
【发布时间】:2013-07-25 19:06:53
【问题描述】:

我有一个第三方 JavaScript 对象,我在该对象上调用一个“搜索”方法,并传入一个搜索查询字符串以及一个搜索完成后要执行的函数。然后,此第三方对象消失并尝试从服务中检索数据。如果服务调用未能在 10 秒内返回,则第三方对象会记录超时错误,但遗憾的是不会执行状态为“超时”或其他适用状态的回调函数。

为了在超时时执行回调,我按照以下代码包装了第三方对象调用:

var SEARCH_TIMEOUT_MILLISECONDS = 10500;

var thirdPartyObject = ... // Global variable

function search(searchTerm, onCompleteCallback) {

    var searchTimeoutHandler = setTimeout(function () {
        onCompleteCallback(null, 'TIMEOUT');
    }, SEARCH_TIMEOUT_MILLISECONDS);

    thirdPartyObject.search({
        searchTerm: searchTerm,
        onComplete: function (searchResponse, status) {

            clearTimeout(searchTimeoutHandler);

            onCompleteCallback(searchResponse, status);
        }
    });
}

在创建闭包的地方,如果这个函数被调用了数百次(有些是同时调用的),在 setTimeout 函数被调用或不被调用的场景中是否会出现内存问题?

【问题讨论】:

  • 这里最糟糕的是timeout函数似乎并没有中止搜索,所以如果搜索在10.5秒后返回,那么onCompleteCallback(searchResponse, status)将被执行,尽管onCompleteCallback(null, 'TIMEOUT')已经被执行了。跨度>

标签: javascript callback timeout closures settimeout


【解决方案1】:

不,不应该有任何内存泄漏。就超时而言,只有两种情况:

  • 超时处理程序被调用,之后它被垃圾回收。
  • 超时被清除,之后也被垃圾回收。

但是,如果您进行了数百次多次搜索,那些超时处理程序可能会堆积起来,但它们最终会被清除(在最多使用n * SEARCH_TIMEOUT_MILLISECONDS 之后,其中nsearch 的次数已被调用,这也是您将拥有的超时处理程序实例的数量)。所以本身没有内存泄漏,但你可以让事情堆积起来。您可能需要调整 SEARCH_TIMEOUT_MILLISECONDS 变量,以免堆积。您还可以在 Chrome 开发者工具上查看内存使用情况,了解有多少内存已用完。

【讨论】:

  • 感谢您的回答。一旦调用超时处理程序但不完全确定,闭包应该被垃圾收集是有道理的。必须更多地了解 Chrome 中的内存使用工具。
猜你喜欢
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 2021-09-25
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多