【发布时间】:2016-02-09 01:09:00
【问题描述】:
更新:在长时间的 jslint 会话之后,问题神秘地消失了,所以我必须得出结论,这是我的代码中某处的一些愚蠢错误,通过删除一些看似无害的错字得到了修复。 p>
最初的问题
我有一个页面通过 jQuery .post 调用加载大量(随机变量)AJAX 对象。
所以我会产生很多电话,例如
/entry/get/orange
/entry/get/red
/entry/get/yellow
/entry/get/red <--- duplicate!
/entry/get/red <--- again!
/entry/get/yellow
/entry/get/red <--- dude, what's wrong with you?
...
当以这种方式运行时,一切都按其应有的方式运行,除了它非常非常低效,并且非常不必要地访问服务器。
解决方案尝试
所以我通过 Promise 切换到缓存,如下所示:
// I have a global colorCache variable
function retrieve(color, callback) {
console.log("retrieving " + color);
var found = -1;
// Each entry in colorCache is an object with some other values
for (var i in colorCache) {
if (colorCache[i].color === color) {
found = i;
break;
}
}
if (found < 0) {
console.log("effecting call for " + color);
var url = "blah/blah/blah/" + color;
var ppar = {
foo: "bar",
answer: 42
};
/* push returns the new length of colorCache */
found = colorCache.push({
color : color,
promise : $.post(url, ppar),
ts : new Date().getTime()
}) - 1;
} else {
console.log("cache hit for " + color);
}
// now found is valid. Return the Promise too, for appending.
return colorCache[found].success(callback);
}
这样,如果相关的.post 已经发出,则使用相同的数据再次调用回调,无论调用本身已经终止还是仍在进行中。
再次,一切正常。 显然。
现在我有另一个问题
有了这个新版本,
- 页面加载
- 所有对象都已加载(比以前快得多 - 正如预期的那样)
- 页面停止,一切都静止了……没有动画,没有时钟,什么都没有……
- ...但 Process Explorer 现在显示 Firefox 不断占用 26-30% 的 CPU。它会继续这样做,直到并且除非我关闭加载页面的选项卡。此外,Firefox 内存消耗稳步上升。我看到它在不到一个小时的时间里从 800M 上升到 1.7GB,不是完全有规律的,而是有明显的上升趋势。
这可能是什么问题?
重要提示:Stack Overflow 上有几个“浏览器泄漏”问题和答案,但它们都涉及到分配对象或以某种方式迭代的重复 jQuery 调用。在这里,一旦我运行了大约 50 次 jQuery 调用,就没有其他事情发生了。
我尝试过的(到目前为止)
- 我使用 Firebug 进行了检查:没有控制台警告或错误,没有迹象日志(我调用的所有函数都有一个),没有网络活动(从 Apache 日志服务器端仔细检查)。
- 我查看了内存中的 Firefox 进程;主线程正在运行,但我不擅长解释 Process Explorer 的线程信息 - 它显示了一些关于“forInIterator”的东西,它告诉我的信息很少。
- 似乎除了 CPU 外没有任何活动(网络、Windows 注册表读/写)。
- 我搜索了很多,发现something 可能相关(但可能不相关)。 我还没有尝试过这个建议,但我会尽快尝试,即使我看不到它有什么帮助,而且无论如何我不会使用
when.js,即使有类似的东西可能已经在 jQuery 中蔓延,因为:一个潜在的解决方法是确保 你的承诺回调和 errbacks 返回一些东西(除了 $.Deferred)。 - 按照 Jaromanda X 的建议使用 Promise.resolve 包装 .post 调用,并将缓存对象移动到函数内以避免污染全局范围(这始终是一个好习惯)。
- 直接返回Promise对象,并通过附加外部.then调用回调。
- 用 Chrome 测试。结果相同(在某些方面令人放心),但 CPU 负载恒定为 17%。
- 关闭选项卡可以减轻 CPU 负载。
【问题讨论】:
-
你不需要它是:
return colorCache[found].promise.then(callback);?colorCache[found]是您的对象,它没有您尝试调用的.success()方法。另外,我切换到.then()是为了更好地兼容未来,因为.success()是非标准的。 -
我已经阅读了 jQuery.deferred 不是 Promise/A+ 规范 - 这并不意味着这是这个问题的根源,但是,尝试“包装”
$.post(url, ppar)在本机Promise.resolve($.post(url, ppar))中,看看 cpu 使用问题是否消失 - 另外,这是您的检索函数的 fiddle 不需要全局变量,并简化(我认为)逻辑(没有 for 循环例如,用于查找缓存值)-小提琴包装了本评论中提到的 jQuery -
@JaromandaX ,我试过了,但没有用。我现在将尝试减少调用次数,看看是否能摆脱一些线索。
-
“我有一个页面通过 jQuery .post 调用加载大量(随机变量)AJAX 对象。” - 重新考虑您的架构可能是个好主意 - 我们不会为您提供任何解决方案 - 这是一个架构问题。
-
是否可以选择使用不蹩脚的 promise 库或 request 库?
标签: jquery ajax firefox promise