场景
我有一个工作人员处理项目并通过处理程序函数调用传播结果。
代码
在某些时候,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() -> 等
。
为了打破它,我尝试使用 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();
但这并没有回复这个话题,我仍然想知道答案。
最佳答案
我假设此数据的处理是依赖于顺序的?如果不是,我会尝试对调用处理程序的进程函数进行非递归调用,这样会快得多,而且不会出现堆栈问题!如果您的批处理系统失败,可能是最不糟糕的解决方案。
function _batch(callback){
this.counter = 0;
this.callback = callback;
this.count = function(){
if(this.counter >= 1000){
setTimeout(callback,0);
this.counter = 0;
return false;
}
else
this.counter++
return true;
}
}
如果结果处理程序应该递归则返回 true。
或者潜在的重组?如果没有更多信息,很难知道这是否有效。
var position = 0;
function process()
{
while(1)
{
if(!bDataReady){
setTimeout(process,5);
break;}
//process data
//propagate data
position ++;
if(bComplete)
break
}
}
关于javascript - 高效的调用堆栈中断技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24776091/