我有一个脚本(在下面的示例中简化),其中用户操作启动递归函数。
用户可以在已启动的操作尚未完成运行时启动新操作。
但我想确保任何新动作停止以前的所有操作。
目前实际发生的事情(您可以在下面的示例中看到这一点)是,无论用户启动了多少新操作,每个先前启动的操作都会继续,直到完成为止。
我想知道是否(在下面的例子中)当前一个列表只增加了5个项目并且确保之前的列表不再增长时,是否可以开始增加新列表。
var trigger = document.getElementsByTagName('p')[0];
var o = 0;
function addListItems(orderedList, listItemNumber) {
var listItems = orderedList.getElementsByTagName('li');
if (listItemNumber > 9) {
return;
}
listItems[listItemNumber].classList.add('show');
listItemNumber++;
setTimeout(function(){addListItems(orderedList, listItemNumber)}, 400);
}
function startRecursiveFunction() {
var orderedList = document.getElementsByTagName('ol')[o];
var listItemNumber = 0;
if (o < 7) {
addListItems(orderedList, listItemNumber);
}
o++;
}
trigger.addEventListener('click', startRecursiveFunction, false);
p {
font-weight: bold;
cursor: pointer;
}
ol {
display: inline-block;
}
li {
opacity: 0;
}
li.show {
opacity: 1;
}
<p>Click to trigger function (up to 7 times)</p>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
答案 0 :(得分:3)
您可以使用clearTimeout
取消已安排的超时事件。
请注意标有***
的代码的三处更改,这些更改都处理新的timer
变量:
var trigger = document.getElementsByTagName('p')[0];
var o = 0;
var timer; //***
function addListItems(orderedList, listItemNumber) {
var listItems = orderedList.getElementsByTagName('li');
if (listItemNumber > 9) {
return;
}
listItems[listItemNumber].classList.add('show');
listItemNumber++;
// ***
timer = setTimeout(function(){addListItems(orderedList, listItemNumber)}, 400);
}
function startRecursiveFunction() {
var orderedList = document.getElementsByTagName('ol')[o];
var listItemNumber = 0;
clearTimeout(timer); // ***
if (o < 7) {
addListItems(orderedList, listItemNumber);
}
o++;
}
trigger.addEventListener('click', startRecursiveFunction, false);
&#13;
p {
font-weight: bold;
cursor: pointer;
}
ol {
display: inline-block;
}
li {
opacity: 0;
}
li.show {
opacity: 1;
}
&#13;
<p>Click to trigger function (up to 7 times)</p>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
&#13;
但是,我应该补充一点,这不是真正的递归:调用堆栈不会随着每次调用addListItems
而增长,因为前一次调用已经在通过{{启动下一个调用时已经结束事件:在这些调用之间调用堆栈是空的。
它是真正的(同步)递归,你可以对点击事件做任何事情,因为直到递归完成后才会调用那些事件回调。
答案 1 :(得分:2)
您可以使用计数器变量,每次调用startRecursiveFunction
时都会增加该变量。在setTimeout
回调中,检查计数器是否已更改,如果是,则停止递归。
var trigger = document.getElementsByTagName('p')[0];
var o = 0;
var fnId = 0;
function addListItems(orderedList, listItemNumber) {
var listItems = orderedList.getElementsByTagName('li');
if (listItemNumber > 9) {
return;
}
listItems[listItemNumber].classList.add('show');
listItemNumber++;
var lastFnId = fnId;
setTimeout(function() {
if (lastFnId === fnId) {
addListItems(orderedList, listItemNumber);
}
}, 400);
}
function startRecursiveFunction() {
var orderedList = document.getElementsByTagName('ol')[o];
var listItemNumber = 0;
if (o < 7) {
fnId++;
addListItems(orderedList, listItemNumber);
}
o++;
}
trigger.addEventListener('click', startRecursiveFunction, false);
&#13;
p {
font-weight: bold;
cursor: pointer;
}
ol {
display: inline-block;
}
li {
opacity: 0;
}
li.show {
opacity: 1;
}
&#13;
<p>Click to trigger function</p>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ol>
&#13;