如何使用 `requestAnimationFrame` 停止递归循环
How to stop recursive loop with `requestAnimationFrame`
我有一个 class 的递归循环函数,如下所示:
class Foo {
private isLoopOnFlg: boolean = false;
public StartLoop() {
this.isLoopOnFlg = true;
this.recursiveLoopWithDelay(() => {
// Modifying DOM objects
}, 1000);
}
public StopLoop() {
this.isLoopOnFlg = false;
}
// THE PROBLEM
private recursiveLoopWithDelay(loopFn: any, delay: number) {
let stamp = Date.now();
// How do I stop the loop using `isLoopOnFlg`?
function _loop() {
if (Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop);
}
window.requestAnimationFrame(_loop);
}
}
如您所见,函数 recursiveLoopWithDelay
不会停止 - 所以我添加了一个新的私有变量 isLoopOnFlg
并且我想用它来停止递归函数 - 但我我不知道该怎么做。我试图通过在函数中添加一个新参数 keepLoopFlg
来停止该函数,如下所示:
...
private recursiveLoopWithDelay(loopFn: any, delay: number) {
let stamp = Date.now();
// Added a new param `keepLoopFlg` but it's not changed when `StopLoop()` is called
function _loop(keepLoopFlg: boolean) {
if (keepLoopFlg && Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop.bind(this, this.isLoopOnFlg)); // Used `.bind(...)`
}
window.requestAnimationFrame(_loop.bind(this, this.isLoopOnFlg));
}
...
但是上面的代码不会做我想要的 - 当调用 StopLoop()
时,递归函数仍然继续(内存泄漏)。
我很想学习如何使用当前结构停止递归函数并防止内存泄漏。请赐教!
首先,它并不是真正的递归,因为它在事件循环中对回调进行排队,而不是直接调用回调。因此,您不必担心 运行 调用堆栈内存不足。
要停止调用 requestAnimationFrame,您只需不调用它即可。问题是,你想什么时候停止调用它?如果您要为其他人提供实用功能,通常让他们决定何时“取消订阅”或停止更新。
private recursiveLoopWithDelay(loopFn: any, delay: number) {
const self = this;
let stamp = Date.now();
function _loop() {
// If we aren't looping anymore, just exit the code.
// Don't requeue requestAnimationFrame
if (!self.isLoopOn) {
return;
}
if (Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop);
}
window.requestAnimationFrame(_loop);
}
您也可以像我在此处所做的那样使用词法作用域来跳过绑定。将 this
存储在我可以随时查找的变量 self
中。
我有一个 class 的递归循环函数,如下所示:
class Foo {
private isLoopOnFlg: boolean = false;
public StartLoop() {
this.isLoopOnFlg = true;
this.recursiveLoopWithDelay(() => {
// Modifying DOM objects
}, 1000);
}
public StopLoop() {
this.isLoopOnFlg = false;
}
// THE PROBLEM
private recursiveLoopWithDelay(loopFn: any, delay: number) {
let stamp = Date.now();
// How do I stop the loop using `isLoopOnFlg`?
function _loop() {
if (Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop);
}
window.requestAnimationFrame(_loop);
}
}
如您所见,函数 recursiveLoopWithDelay
不会停止 - 所以我添加了一个新的私有变量 isLoopOnFlg
并且我想用它来停止递归函数 - 但我我不知道该怎么做。我试图通过在函数中添加一个新参数 keepLoopFlg
来停止该函数,如下所示:
...
private recursiveLoopWithDelay(loopFn: any, delay: number) {
let stamp = Date.now();
// Added a new param `keepLoopFlg` but it's not changed when `StopLoop()` is called
function _loop(keepLoopFlg: boolean) {
if (keepLoopFlg && Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop.bind(this, this.isLoopOnFlg)); // Used `.bind(...)`
}
window.requestAnimationFrame(_loop.bind(this, this.isLoopOnFlg));
}
...
但是上面的代码不会做我想要的 - 当调用 StopLoop()
时,递归函数仍然继续(内存泄漏)。
我很想学习如何使用当前结构停止递归函数并防止内存泄漏。请赐教!
首先,它并不是真正的递归,因为它在事件循环中对回调进行排队,而不是直接调用回调。因此,您不必担心 运行 调用堆栈内存不足。
要停止调用 requestAnimationFrame,您只需不调用它即可。问题是,你想什么时候停止调用它?如果您要为其他人提供实用功能,通常让他们决定何时“取消订阅”或停止更新。
private recursiveLoopWithDelay(loopFn: any, delay: number) {
const self = this;
let stamp = Date.now();
function _loop() {
// If we aren't looping anymore, just exit the code.
// Don't requeue requestAnimationFrame
if (!self.isLoopOn) {
return;
}
if (Date.now() - stamp >= delay) {
loopFn();
stamp = Date.now();
}
window.requestAnimationFrame(_loop);
}
window.requestAnimationFrame(_loop);
}
您也可以像我在此处所做的那样使用词法作用域来跳过绑定。将 this
存储在我可以随时查找的变量 self
中。