我有一个脚本,允许我在画布上显示网络摄像头并下载'某些间隔内的特定帧。 当时间参数很大(每2秒捕获30分钟)时,我遇到了麻烦。它可以顺利运行大约15分钟,然后崩溃(firefox因内存不足错误而关闭)。此外,重新启动Firefox后,有时会在3-4分钟内拍摄许多0字节的照片,然后再次开始工作。我在实验室放置的旧2 GB RAM机器上运行它,有没有办法减少内存使用量?
以下是包含参数和函数realizarCapturas
的代码段。
我可以添加静止代码,但我认为要优化的部分应该是这个。
var frecuenciaComienzoCaptura = 1; // how long till next capture
var frecuenciaCaptura = 3; //seconds between photos
var duracion = 5; // amount of photos to capture
function realizarCapturas(){
var i = 1;
var interval = setInterval(function(){
if(i <= duracion){
context.drawImage(video, 0, 0, 640, 480);
var imagen = document.getElementById("imagen");
imagen.href = canvas.toDataURL("image/png");
var now = new Date();
var filename = formatNumber(now.getHours()) + "-" + formatNumber(now.getMinutes()) + "-" + formatNumber(now.getSeconds());
imagen.download = filename + ".png"; // Make sure the browser downloads the image
imagen.click(); // Trigger the click
i = i+1;
}else{
clearInterval(interval);
}
}, frecuenciaCaptura * 1000);
}
setInterval(function(){
realizarCapturas();
}, frecuenciaComienzoCaptura * 1000 * 60 * 60);
realizarCapturas();
}, false);
答案 0 :(得分:1)
通常不要使用setInterval
因为它可能是调用堆栈溢出的源,这在代码中很难检测到。
您的问题是您没有清除所生成的所有间隔,因此每隔3秒就会创建一个新的间隔事件。最终,运行一小段代码所花费的时间将比您创建的所有间隔事件所能管理的时间长,因此每个间隔将继续将它们的事件推送到调用堆栈但是没有机会成为运行直到堆栈上放置更多间隔,最终导致崩溃。 setInterval也不保证事件之间的时间准确。
请改用setTimeout
。这样你就可以根据需要生成事件,而不必保留关闭事件的句柄。
以下是您编写的代码,以便您永远不会有调用堆栈溢出。
var frecuenciaComienzoCaptura = 1 * 1000* 60 * 60; // how long till next capture
var frecuenciaCaptura = 3 * 1000; //seconds between photos
var duracion = 5; // amount of photos to capture
var counter = 0;
// the capture function
var captura = function () {
counter = counter + 1;
if(counter < duracion){ // do we need more images?
// only create timer events as needed.
setTimeout(captura, frecuenciaCaptura); //set time till next image
}
context.drawImage(video, 0, 0, 640, 480);
var imagen = document.getElementById("imagen");
imagen.href = canvas.toDataURL("image/png");
var now = new Date();
var filename = formatNumber(now.getHours()) + "-" + formatNumber(now.getMinutes()) + "-" + formatNumber(now.getSeconds());
imagen.download = filename + ".png"; // Make sure the browser downloads the image
imagen.click(); // Trigger the click
}
function realizarCapturas() {
// request next batch of captures by only creating one timer event as we need
setTimeout(realizarCapturas,frecuenciaComienzoCaptura);
counter = 0; // reset counter
captura(); // capture timages
}
// start captures.
realizarCapturas();