【发布时间】:2014-09-06 16:54:32
【问题描述】:
场景
我有一个工作人员处理项目并通过处理程序函数调用传播结果。
代码
在某些时候,Worker 在processNextItem() 调用和resultHandler() 回调之间在内部调用异步方法,这会重置调用堆栈:
function Worker(resultHandler) {
this.processNextItem = function () {
// some work
...
// propagate result
resultHandler(someResult);
}
}
var myResultHandler = function (result) {
// Process result
...
// Process next item
worker.processNextItem();
};
var worker = new Worker(myResultHandler);
// Start working on first item
Worker.processNextItem();
但这种情况发生得不够频繁,有时我会得到 Uncaught RangeError: Maximum call stack size exceeded,因为递归调用:
processNextItem() -> resultHandler() -> processNextItem() -> resultHandler() -> processNextItem() -> resultHandler() -> etc.
为了打破它,我尝试使用setTimeout:
this.processNextItem = function () {
// some work
...
// propagate result
setTimeout(function () { resultHandler(someResult); }, 0);
}
但这会大大降低性能(我有数百个项目要处理)。
问题
有没有办法通过异步调用中断调用堆栈,但比setTimeout 更有效?或者我应该手动计算同步调用并每 1000 次调用一次 setTimeout 吗?
我的解决方案:解决方法
最初我解决了这个问题,@nepeo 写道:创建了一个同步回调计数器,并使每 1000 个回调异步。这显然是一种解决方法,因为调用堆栈限制因浏览器而异(可能因平台和版本而异)。
最终我通过批处理结果解决了这个问题:
function Worker(resultHandler) {
this.processNextBatch = function () {
// some ASYNC work
...
// propagate results
resultsHandler(someResults);
}
}
var myResultsHandler = function (results) {
results.forEach(function (result) {
// Process result
...
});
// Process next item
worker.processNextBatch();
};
var worker = new Worker(myResultsHandler);
// Start working on first item
Worker.processNextBatch();
但这并没有回复这个帖子,我仍然想知道答案。
【问题讨论】:
标签: javascript callstack