我正在使用一个名为timer.js的库,因为我想遍历一个数组,但希望在迭代之间有一个延迟
这是图书馆的github:https://github.com/husa/timer.js
的链接我做了什么,从我的主要js文件之前创建了一个文件形式的最小版本的timer.js并链接到它的html主体:
<script src="./timer.js" charset="utf-8"></script>
<script src="./script.js" charset="utf-8"></script>
然后在主js文件中我创建了一个数字数组,我只想循环遍历它们,同时在console.logs之间有一个间隔:
var timer = new Timer();
var nums = [1,2,3,4]
for (var i = 0; i < nums.length; i++){
timer.start(5).on('end', function(){
console.log(i);
})
}
当我打开控制台日志时,我只得到一个&#39; 4&#39;登录。为什么for循环不适用于其他索引。另外,有没有办法用forEach函数重新创建它?
谢谢
答案 0 :(得分:1)
我想循环遍历一个数组,但希望在迭代之间有一个延迟
根据迭代设置持续时间:
duration*iteration
setTimeout可以实现延迟,持续时间以毫秒为单位,比如说2秒(2000ms),让我们为迭代添加1,这样第一次迭代就会有延迟:
const nums = [1,2,3,4]
nums.forEach((n, i)=>{
setTimeout(()=>(
console.log(i)
), 2000*(i+1))
});
答案 1 :(得分:1)
在处理异步代码时,你遇到了一些常见的陷阱。
首先要意识到你的for循环是而不是等待每次迭代完成。它只是尽可能快地调用timer.start(5)
四次。为此,您不能使用for循环。您最好的选择是使用非常受欢迎的async库中的内容。
要意识到的第二件事是你在同一个实例上重复调用start(5)
,导致它每次重置为5秒。因此,只有一个预定的回调被调用,循环完成后五秒。这实际上不是对异步代码的误解,而是对timer.js
库本身的误解。您可以通过在循环中创建新的计时器来解决此问题,但对于您的情况timer.js
有点矫枉过正。您可以使用原生setTimeout
来电完全按照您的要求执行操作。
要实现的第三件事是,您发送给on()
的回调不会存储i
的当前值。它只是存储对该变量的引用,因此对该变量的任何更改最终都会反映在日志中。
在循环的最后一次迭代期间,i
的值实际上是3而不是4.这是因为4不是<
nums.length。那么,执行的唯一回调应该记录3,对吗?
i
的值。因此,i
从3变为4,然后检查它是否为<
nums.length,并且由于它不是,它会退出。然后,五秒钟后,您的回调会记录i
的值,现在为4。
这是Javascript中名为closure的属性。我绝对建议阅读该链接,因为这个概念对于有效使用该语言非常重要。
无论如何,因为您可能正在寻找正确的代码,所以我会使用async
和setTimeout
来执行您尝试的操作:
var nums = [1,2,3,4];
async.eachSeries(nums, (num, done) => {
setTimeout(() => {
console.log(num);
done();
}, 5000);
});